github.com/cryptogateway/go-paymex@v0.0.0-20210204174735-96277fb1e602/cmd/utils/flags.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package utils contains internal helper functions for go-ethereum commands. 18 package utils 19 20 import ( 21 "crypto/ecdsa" 22 "fmt" 23 "io" 24 "io/ioutil" 25 "math/big" 26 "os" 27 "path/filepath" 28 "strconv" 29 "strings" 30 "text/tabwriter" 31 "text/template" 32 "time" 33 34 "github.com/cryptogateway/go-paymex/accounts" 35 "github.com/cryptogateway/go-paymex/accounts/keystore" 36 "github.com/cryptogateway/go-paymex/common" 37 "github.com/cryptogateway/go-paymex/common/fdlimit" 38 "github.com/cryptogateway/go-paymex/consensus" 39 "github.com/cryptogateway/go-paymex/consensus/clique" 40 "github.com/cryptogateway/go-paymex/consensus/ethash" 41 "github.com/cryptogateway/go-paymex/core" 42 "github.com/cryptogateway/go-paymex/core/rawdb" 43 "github.com/cryptogateway/go-paymex/core/vm" 44 "github.com/cryptogateway/go-paymex/crypto" 45 "github.com/cryptogateway/go-paymex/eth" 46 "github.com/cryptogateway/go-paymex/eth/downloader" 47 "github.com/cryptogateway/go-paymex/eth/gasprice" 48 "github.com/cryptogateway/go-paymex/eth/tracers" 49 "github.com/cryptogateway/go-paymex/ethdb" 50 "github.com/cryptogateway/go-paymex/ethstats" 51 "github.com/cryptogateway/go-paymex/graphql" 52 "github.com/cryptogateway/go-paymex/internal/ethapi" 53 "github.com/cryptogateway/go-paymex/internal/flags" 54 "github.com/cryptogateway/go-paymex/les" 55 "github.com/cryptogateway/go-paymex/log" 56 "github.com/cryptogateway/go-paymex/metrics" 57 "github.com/cryptogateway/go-paymex/metrics/exp" 58 "github.com/cryptogateway/go-paymex/metrics/influxdb" 59 "github.com/cryptogateway/go-paymex/miner" 60 "github.com/cryptogateway/go-paymex/node" 61 "github.com/cryptogateway/go-paymex/p2p" 62 "github.com/cryptogateway/go-paymex/p2p/enode" 63 "github.com/cryptogateway/go-paymex/p2p/nat" 64 "github.com/cryptogateway/go-paymex/p2p/netutil" 65 "github.com/cryptogateway/go-paymex/params" 66 pcsclite "github.com/gballet/go-libpcsclite" 67 "gopkg.in/urfave/cli.v1" 68 ) 69 70 func init() { 71 cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] 72 73 VERSION: 74 {{.Version}} 75 76 COMMANDS: 77 {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 78 {{end}}{{if .Flags}} 79 GLOBAL OPTIONS: 80 {{range .Flags}}{{.}} 81 {{end}}{{end}} 82 ` 83 cli.CommandHelpTemplate = flags.CommandHelpTemplate 84 cli.HelpPrinter = printHelp 85 } 86 87 func printHelp(out io.Writer, templ string, data interface{}) { 88 funcMap := template.FuncMap{"join": strings.Join} 89 t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) 90 w := tabwriter.NewWriter(out, 38, 8, 2, ' ', 0) 91 err := t.Execute(w, data) 92 if err != nil { 93 panic(err) 94 } 95 w.Flush() 96 } 97 98 // These are all the command line flags we support. 99 // If you add to this list, please remember to include the 100 // flag in the appropriate command definition. 101 // 102 // The flags are defined here so their names and help texts 103 // are the same for all commands. 104 105 var ( 106 // General settings 107 DataDirFlag = DirectoryFlag{ 108 Name: "datadir", 109 Usage: "Data directory for the databases and keystore", 110 Value: DirectoryString(node.DefaultDataDir()), 111 } 112 AncientFlag = DirectoryFlag{ 113 Name: "datadir.ancient", 114 Usage: "Data directory for ancient chain segments (default = inside chaindata)", 115 } 116 MinFreeDiskSpaceFlag = DirectoryFlag{ 117 Name: "datadir.minfreedisk", 118 Usage: "Minimum free disk space in MB, once reached triggers auto shut down (default = --cache.gc converted to MB, 0 = disabled)", 119 } 120 KeyStoreDirFlag = DirectoryFlag{ 121 Name: "keystore", 122 Usage: "Directory for the keystore (default = inside the datadir)", 123 } 124 NoUSBFlag = cli.BoolFlag{ 125 Name: "nousb", 126 Usage: "Disables monitoring for and managing USB hardware wallets (deprecated)", 127 } 128 USBFlag = cli.BoolFlag{ 129 Name: "usb", 130 Usage: "Enable monitoring and management of USB hardware wallets", 131 } 132 SmartCardDaemonPathFlag = cli.StringFlag{ 133 Name: "pcscdpath", 134 Usage: "Path to the smartcard daemon (pcscd) socket file", 135 Value: pcsclite.PCSCDSockName, 136 } 137 NetworkIdFlag = cli.Uint64Flag{ 138 Name: "networkid", 139 Usage: "Explicitly set network id (integer)(For testnets: use --ropsten, --rinkeby, --goerli instead)", 140 Value: eth.DefaultConfig.NetworkId, 141 } 142 MainnetFlag = cli.BoolFlag{ 143 Name: "mainnet", 144 Usage: "Ethereum mainnet", 145 } 146 GoerliFlag = cli.BoolFlag{ 147 Name: "goerli", 148 Usage: "Görli network: pre-configured proof-of-authority test network", 149 } 150 YoloV3Flag = cli.BoolFlag{ 151 Name: "yolov3", 152 Usage: "YOLOv3 network: pre-configured proof-of-authority shortlived test network.", 153 } 154 RinkebyFlag = cli.BoolFlag{ 155 Name: "rinkeby", 156 Usage: "Rinkeby network: pre-configured proof-of-authority test network", 157 } 158 RopstenFlag = cli.BoolFlag{ 159 Name: "ropsten", 160 Usage: "Ropsten network: pre-configured proof-of-work test network", 161 } 162 DeveloperFlag = cli.BoolFlag{ 163 Name: "dev", 164 Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled", 165 } 166 DeveloperPeriodFlag = cli.IntFlag{ 167 Name: "dev.period", 168 Usage: "Block period to use in developer mode (0 = mine only if transaction pending)", 169 } 170 IdentityFlag = cli.StringFlag{ 171 Name: "identity", 172 Usage: "Custom node name", 173 } 174 DocRootFlag = DirectoryFlag{ 175 Name: "docroot", 176 Usage: "Document Root for HTTPClient file scheme", 177 Value: DirectoryString(HomeDir()), 178 } 179 ExitWhenSyncedFlag = cli.BoolFlag{ 180 Name: "exitwhensynced", 181 Usage: "Exits after block synchronisation completes", 182 } 183 IterativeOutputFlag = cli.BoolFlag{ 184 Name: "iterative", 185 Usage: "Print streaming JSON iteratively, delimited by newlines", 186 } 187 ExcludeStorageFlag = cli.BoolFlag{ 188 Name: "nostorage", 189 Usage: "Exclude storage entries (save db lookups)", 190 } 191 IncludeIncompletesFlag = cli.BoolFlag{ 192 Name: "incompletes", 193 Usage: "Include accounts for which we don't have the address (missing preimage)", 194 } 195 ExcludeCodeFlag = cli.BoolFlag{ 196 Name: "nocode", 197 Usage: "Exclude contract code (save db lookups)", 198 } 199 defaultSyncMode = eth.DefaultConfig.SyncMode 200 SyncModeFlag = TextMarshalerFlag{ 201 Name: "syncmode", 202 Usage: `Blockchain sync mode ("fast", "full", "snap" or "light")`, 203 Value: &defaultSyncMode, 204 } 205 GCModeFlag = cli.StringFlag{ 206 Name: "gcmode", 207 Usage: `Blockchain garbage collection mode ("full", "archive")`, 208 Value: "full", 209 } 210 SnapshotFlag = cli.BoolFlag{ 211 Name: "snapshot", 212 Usage: `Enables snapshot-database mode -- experimental work in progress feature`, 213 } 214 TxLookupLimitFlag = cli.Int64Flag{ 215 Name: "txlookuplimit", 216 Usage: "Number of recent blocks to maintain transactions index by-hash for (default = index all blocks)", 217 Value: 0, 218 } 219 LightKDFFlag = cli.BoolFlag{ 220 Name: "lightkdf", 221 Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", 222 } 223 WhitelistFlag = cli.StringFlag{ 224 Name: "whitelist", 225 Usage: "Comma separated block number-to-hash mappings to enforce (<number>=<hash>)", 226 } 227 // Light server and client settings 228 LightServeFlag = cli.IntFlag{ 229 Name: "light.serve", 230 Usage: "Maximum percentage of time allowed for serving LES requests (multi-threaded processing allows values over 100)", 231 Value: eth.DefaultConfig.LightServ, 232 } 233 LightIngressFlag = cli.IntFlag{ 234 Name: "light.ingress", 235 Usage: "Incoming bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)", 236 Value: eth.DefaultConfig.LightIngress, 237 } 238 LightEgressFlag = cli.IntFlag{ 239 Name: "light.egress", 240 Usage: "Outgoing bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)", 241 Value: eth.DefaultConfig.LightEgress, 242 } 243 LightMaxPeersFlag = cli.IntFlag{ 244 Name: "light.maxpeers", 245 Usage: "Maximum number of light clients to serve, or light servers to attach to", 246 Value: eth.DefaultConfig.LightPeers, 247 } 248 UltraLightServersFlag = cli.StringFlag{ 249 Name: "ulc.servers", 250 Usage: "List of trusted ultra-light servers", 251 Value: strings.Join(eth.DefaultConfig.UltraLightServers, ","), 252 } 253 UltraLightFractionFlag = cli.IntFlag{ 254 Name: "ulc.fraction", 255 Usage: "Minimum % of trusted ultra-light servers required to announce a new head", 256 Value: eth.DefaultConfig.UltraLightFraction, 257 } 258 UltraLightOnlyAnnounceFlag = cli.BoolFlag{ 259 Name: "ulc.onlyannounce", 260 Usage: "Ultra light server sends announcements only", 261 } 262 LightNoPruneFlag = cli.BoolFlag{ 263 Name: "light.nopruning", 264 Usage: "Disable ancient light chain data pruning", 265 } 266 // Ethash settings 267 EthashCacheDirFlag = DirectoryFlag{ 268 Name: "ethash.cachedir", 269 Usage: "Directory to store the ethash verification caches (default = inside the datadir)", 270 } 271 EthashCachesInMemoryFlag = cli.IntFlag{ 272 Name: "ethash.cachesinmem", 273 Usage: "Number of recent ethash caches to keep in memory (16MB each)", 274 Value: eth.DefaultConfig.Ethash.CachesInMem, 275 } 276 EthashCachesOnDiskFlag = cli.IntFlag{ 277 Name: "ethash.cachesondisk", 278 Usage: "Number of recent ethash caches to keep on disk (16MB each)", 279 Value: eth.DefaultConfig.Ethash.CachesOnDisk, 280 } 281 EthashCachesLockMmapFlag = cli.BoolFlag{ 282 Name: "ethash.cacheslockmmap", 283 Usage: "Lock memory maps of recent ethash caches", 284 } 285 EthashDatasetDirFlag = DirectoryFlag{ 286 Name: "ethash.dagdir", 287 Usage: "Directory to store the ethash mining DAGs", 288 Value: DirectoryString(eth.DefaultConfig.Ethash.DatasetDir), 289 } 290 EthashDatasetsInMemoryFlag = cli.IntFlag{ 291 Name: "ethash.dagsinmem", 292 Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)", 293 Value: eth.DefaultConfig.Ethash.DatasetsInMem, 294 } 295 EthashDatasetsOnDiskFlag = cli.IntFlag{ 296 Name: "ethash.dagsondisk", 297 Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)", 298 Value: eth.DefaultConfig.Ethash.DatasetsOnDisk, 299 } 300 EthashDatasetsLockMmapFlag = cli.BoolFlag{ 301 Name: "ethash.dagslockmmap", 302 Usage: "Lock memory maps for recent ethash mining DAGs", 303 } 304 // Transaction pool settings 305 TxPoolLocalsFlag = cli.StringFlag{ 306 Name: "txpool.locals", 307 Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)", 308 } 309 TxPoolNoLocalsFlag = cli.BoolFlag{ 310 Name: "txpool.nolocals", 311 Usage: "Disables price exemptions for locally submitted transactions", 312 } 313 TxPoolJournalFlag = cli.StringFlag{ 314 Name: "txpool.journal", 315 Usage: "Disk journal for local transaction to survive node restarts", 316 Value: core.DefaultTxPoolConfig.Journal, 317 } 318 TxPoolRejournalFlag = cli.DurationFlag{ 319 Name: "txpool.rejournal", 320 Usage: "Time interval to regenerate the local transaction journal", 321 Value: core.DefaultTxPoolConfig.Rejournal, 322 } 323 TxPoolPriceLimitFlag = cli.Uint64Flag{ 324 Name: "txpool.pricelimit", 325 Usage: "Minimum gas price limit to enforce for acceptance into the pool", 326 Value: eth.DefaultConfig.TxPool.PriceLimit, 327 } 328 TxPoolPriceBumpFlag = cli.Uint64Flag{ 329 Name: "txpool.pricebump", 330 Usage: "Price bump percentage to replace an already existing transaction", 331 Value: eth.DefaultConfig.TxPool.PriceBump, 332 } 333 TxPoolAccountSlotsFlag = cli.Uint64Flag{ 334 Name: "txpool.accountslots", 335 Usage: "Minimum number of executable transaction slots guaranteed per account", 336 Value: eth.DefaultConfig.TxPool.AccountSlots, 337 } 338 TxPoolGlobalSlotsFlag = cli.Uint64Flag{ 339 Name: "txpool.globalslots", 340 Usage: "Maximum number of executable transaction slots for all accounts", 341 Value: eth.DefaultConfig.TxPool.GlobalSlots, 342 } 343 TxPoolAccountQueueFlag = cli.Uint64Flag{ 344 Name: "txpool.accountqueue", 345 Usage: "Maximum number of non-executable transaction slots permitted per account", 346 Value: eth.DefaultConfig.TxPool.AccountQueue, 347 } 348 TxPoolGlobalQueueFlag = cli.Uint64Flag{ 349 Name: "txpool.globalqueue", 350 Usage: "Maximum number of non-executable transaction slots for all accounts", 351 Value: eth.DefaultConfig.TxPool.GlobalQueue, 352 } 353 TxPoolLifetimeFlag = cli.DurationFlag{ 354 Name: "txpool.lifetime", 355 Usage: "Maximum amount of time non-executable transaction are queued", 356 Value: eth.DefaultConfig.TxPool.Lifetime, 357 } 358 // Performance tuning settings 359 CacheFlag = cli.IntFlag{ 360 Name: "cache", 361 Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node, 128 light mode)", 362 Value: 1024, 363 } 364 CacheDatabaseFlag = cli.IntFlag{ 365 Name: "cache.database", 366 Usage: "Percentage of cache memory allowance to use for database io", 367 Value: 50, 368 } 369 CacheTrieFlag = cli.IntFlag{ 370 Name: "cache.trie", 371 Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)", 372 Value: 15, 373 } 374 CacheTrieJournalFlag = cli.StringFlag{ 375 Name: "cache.trie.journal", 376 Usage: "Disk journal directory for trie cache to survive node restarts", 377 Value: eth.DefaultConfig.TrieCleanCacheJournal, 378 } 379 CacheTrieRejournalFlag = cli.DurationFlag{ 380 Name: "cache.trie.rejournal", 381 Usage: "Time interval to regenerate the trie cache journal", 382 Value: eth.DefaultConfig.TrieCleanCacheRejournal, 383 } 384 CacheGCFlag = cli.IntFlag{ 385 Name: "cache.gc", 386 Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)", 387 Value: 25, 388 } 389 CacheSnapshotFlag = cli.IntFlag{ 390 Name: "cache.snapshot", 391 Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)", 392 Value: 10, 393 } 394 CacheNoPrefetchFlag = cli.BoolFlag{ 395 Name: "cache.noprefetch", 396 Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)", 397 } 398 CachePreimagesFlag = cli.BoolTFlag{ 399 Name: "cache.preimages", 400 Usage: "Enable recording the SHA3/keccak preimages of trie keys (default: true)", 401 } 402 // Miner settings 403 MiningEnabledFlag = cli.BoolFlag{ 404 Name: "mine", 405 Usage: "Enable mining", 406 } 407 MinerThreadsFlag = cli.IntFlag{ 408 Name: "miner.threads", 409 Usage: "Number of CPU threads to use for mining", 410 Value: 0, 411 } 412 MinerNotifyFlag = cli.StringFlag{ 413 Name: "miner.notify", 414 Usage: "Comma separated HTTP URL list to notify of new work packages", 415 } 416 MinerGasTargetFlag = cli.Uint64Flag{ 417 Name: "miner.gastarget", 418 Usage: "Target gas floor for mined blocks", 419 Value: eth.DefaultConfig.Miner.GasFloor, 420 } 421 MinerGasLimitFlag = cli.Uint64Flag{ 422 Name: "miner.gaslimit", 423 Usage: "Target gas ceiling for mined blocks", 424 Value: eth.DefaultConfig.Miner.GasCeil, 425 } 426 MinerGasPriceFlag = BigFlag{ 427 Name: "miner.gasprice", 428 Usage: "Minimum gas price for mining a transaction", 429 Value: eth.DefaultConfig.Miner.GasPrice, 430 } 431 MinerEtherbaseFlag = cli.StringFlag{ 432 Name: "miner.etherbase", 433 Usage: "Public address for block mining rewards (default = first account)", 434 Value: "0", 435 } 436 MinerExtraDataFlag = cli.StringFlag{ 437 Name: "miner.extradata", 438 Usage: "Block extra data set by the miner (default = client version)", 439 } 440 MinerRecommitIntervalFlag = cli.DurationFlag{ 441 Name: "miner.recommit", 442 Usage: "Time interval to recreate the block being mined", 443 Value: eth.DefaultConfig.Miner.Recommit, 444 } 445 MinerNoVerfiyFlag = cli.BoolFlag{ 446 Name: "miner.noverify", 447 Usage: "Disable remote sealing verification", 448 } 449 // Account settings 450 UnlockedAccountFlag = cli.StringFlag{ 451 Name: "unlock", 452 Usage: "Comma separated list of accounts to unlock", 453 Value: "", 454 } 455 PasswordFileFlag = cli.StringFlag{ 456 Name: "password", 457 Usage: "Password file to use for non-interactive password input", 458 Value: "", 459 } 460 ExternalSignerFlag = cli.StringFlag{ 461 Name: "signer", 462 Usage: "External signer (url or path to ipc file)", 463 Value: "", 464 } 465 VMEnableDebugFlag = cli.BoolFlag{ 466 Name: "vmdebug", 467 Usage: "Record information useful for VM and contract debugging", 468 } 469 InsecureUnlockAllowedFlag = cli.BoolFlag{ 470 Name: "allow-insecure-unlock", 471 Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http", 472 } 473 RPCGlobalGasCapFlag = cli.Uint64Flag{ 474 Name: "rpc.gascap", 475 Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", 476 Value: eth.DefaultConfig.RPCGasCap, 477 } 478 RPCGlobalTxFeeCapFlag = cli.Float64Flag{ 479 Name: "rpc.txfeecap", 480 Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)", 481 Value: eth.DefaultConfig.RPCTxFeeCap, 482 } 483 // Logging and debug settings 484 EthStatsURLFlag = cli.StringFlag{ 485 Name: "ethstats", 486 Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", 487 } 488 FakePoWFlag = cli.BoolFlag{ 489 Name: "fakepow", 490 Usage: "Disables proof-of-work verification", 491 } 492 NoCompactionFlag = cli.BoolFlag{ 493 Name: "nocompaction", 494 Usage: "Disables db compaction after import", 495 } 496 // RPC settings 497 IPCDisabledFlag = cli.BoolFlag{ 498 Name: "ipcdisable", 499 Usage: "Disable the IPC-RPC server", 500 } 501 IPCPathFlag = DirectoryFlag{ 502 Name: "ipcpath", 503 Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", 504 } 505 HTTPEnabledFlag = cli.BoolFlag{ 506 Name: "http", 507 Usage: "Enable the HTTP-RPC server", 508 } 509 HTTPListenAddrFlag = cli.StringFlag{ 510 Name: "http.addr", 511 Usage: "HTTP-RPC server listening interface", 512 Value: node.DefaultHTTPHost, 513 } 514 HTTPPortFlag = cli.IntFlag{ 515 Name: "http.port", 516 Usage: "HTTP-RPC server listening port", 517 Value: node.DefaultHTTPPort, 518 } 519 HTTPCORSDomainFlag = cli.StringFlag{ 520 Name: "http.corsdomain", 521 Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", 522 Value: "", 523 } 524 HTTPVirtualHostsFlag = cli.StringFlag{ 525 Name: "http.vhosts", 526 Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", 527 Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","), 528 } 529 HTTPApiFlag = cli.StringFlag{ 530 Name: "http.api", 531 Usage: "API's offered over the HTTP-RPC interface", 532 Value: "", 533 } 534 HTTPPathPrefixFlag = cli.StringFlag{ 535 Name: "http.rpcprefix", 536 Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", 537 Value: "", 538 } 539 GraphQLEnabledFlag = cli.BoolFlag{ 540 Name: "graphql", 541 Usage: "Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.", 542 } 543 GraphQLCORSDomainFlag = cli.StringFlag{ 544 Name: "graphql.corsdomain", 545 Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", 546 Value: "", 547 } 548 GraphQLVirtualHostsFlag = cli.StringFlag{ 549 Name: "graphql.vhosts", 550 Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", 551 Value: strings.Join(node.DefaultConfig.GraphQLVirtualHosts, ","), 552 } 553 WSEnabledFlag = cli.BoolFlag{ 554 Name: "ws", 555 Usage: "Enable the WS-RPC server", 556 } 557 WSListenAddrFlag = cli.StringFlag{ 558 Name: "ws.addr", 559 Usage: "WS-RPC server listening interface", 560 Value: node.DefaultWSHost, 561 } 562 WSPortFlag = cli.IntFlag{ 563 Name: "ws.port", 564 Usage: "WS-RPC server listening port", 565 Value: node.DefaultWSPort, 566 } 567 WSApiFlag = cli.StringFlag{ 568 Name: "ws.api", 569 Usage: "API's offered over the WS-RPC interface", 570 Value: "", 571 } 572 WSAllowedOriginsFlag = cli.StringFlag{ 573 Name: "ws.origins", 574 Usage: "Origins from which to accept websockets requests", 575 Value: "", 576 } 577 WSPathPrefixFlag = cli.StringFlag{ 578 Name: "ws.rpcprefix", 579 Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", 580 Value: "", 581 } 582 ExecFlag = cli.StringFlag{ 583 Name: "exec", 584 Usage: "Execute JavaScript statement", 585 } 586 PreloadJSFlag = cli.StringFlag{ 587 Name: "preload", 588 Usage: "Comma separated list of JavaScript files to preload into the console", 589 } 590 591 // Network Settings 592 MaxPeersFlag = cli.IntFlag{ 593 Name: "maxpeers", 594 Usage: "Maximum number of network peers (network disabled if set to 0)", 595 Value: node.DefaultConfig.P2P.MaxPeers, 596 } 597 MaxPendingPeersFlag = cli.IntFlag{ 598 Name: "maxpendpeers", 599 Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", 600 Value: node.DefaultConfig.P2P.MaxPendingPeers, 601 } 602 ListenPortFlag = cli.IntFlag{ 603 Name: "port", 604 Usage: "Network listening port", 605 Value: 30303, 606 } 607 BootnodesFlag = cli.StringFlag{ 608 Name: "bootnodes", 609 Usage: "Comma separated enode URLs for P2P discovery bootstrap", 610 Value: "", 611 } 612 NodeKeyFileFlag = cli.StringFlag{ 613 Name: "nodekey", 614 Usage: "P2P node key file", 615 } 616 NodeKeyHexFlag = cli.StringFlag{ 617 Name: "nodekeyhex", 618 Usage: "P2P node key as hex (for testing)", 619 } 620 NATFlag = cli.StringFlag{ 621 Name: "nat", 622 Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)", 623 Value: "any", 624 } 625 NoDiscoverFlag = cli.BoolFlag{ 626 Name: "nodiscover", 627 Usage: "Disables the peer discovery mechanism (manual peer addition)", 628 } 629 DiscoveryV5Flag = cli.BoolFlag{ 630 Name: "v5disc", 631 Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", 632 } 633 NetrestrictFlag = cli.StringFlag{ 634 Name: "netrestrict", 635 Usage: "Restricts network communication to the given IP networks (CIDR masks)", 636 } 637 DNSDiscoveryFlag = cli.StringFlag{ 638 Name: "discovery.dns", 639 Usage: "Sets DNS discovery entry points (use \"\" to disable DNS)", 640 } 641 642 // ATM the url is left to the user and deployment to 643 JSpathFlag = cli.StringFlag{ 644 Name: "jspath", 645 Usage: "JavaScript root path for `loadScript`", 646 Value: ".", 647 } 648 649 // Gas price oracle settings 650 GpoBlocksFlag = cli.IntFlag{ 651 Name: "gpo.blocks", 652 Usage: "Number of recent blocks to check for gas prices", 653 Value: eth.DefaultConfig.GPO.Blocks, 654 } 655 GpoPercentileFlag = cli.IntFlag{ 656 Name: "gpo.percentile", 657 Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", 658 Value: eth.DefaultConfig.GPO.Percentile, 659 } 660 GpoMaxGasPriceFlag = cli.Int64Flag{ 661 Name: "gpo.maxprice", 662 Usage: "Maximum gas price will be recommended by gpo", 663 Value: eth.DefaultConfig.GPO.MaxPrice.Int64(), 664 } 665 WhisperEnabledFlag = cli.BoolFlag{ 666 Name: "shh", 667 Usage: "Enable Whisper", 668 } 669 WhisperMaxMessageSizeFlag = cli.IntFlag{ 670 Name: "shh.maxmessagesize", 671 Usage: "Max message size accepted", 672 Value: 1024 * 1024, 673 } 674 WhisperMinPOWFlag = cli.Float64Flag{ 675 Name: "shh.pow", 676 Usage: "Minimum POW accepted", 677 Value: 0.2, 678 } 679 WhisperRestrictConnectionBetweenLightClientsFlag = cli.BoolFlag{ 680 Name: "shh.restrict-light", 681 Usage: "Restrict connection between two whisper light clients", 682 } 683 684 // Metrics flags 685 MetricsEnabledFlag = cli.BoolFlag{ 686 Name: "metrics", 687 Usage: "Enable metrics collection and reporting", 688 } 689 MetricsEnabledExpensiveFlag = cli.BoolFlag{ 690 Name: "metrics.expensive", 691 Usage: "Enable expensive metrics collection and reporting", 692 } 693 694 // MetricsHTTPFlag defines the endpoint for a stand-alone metrics HTTP endpoint. 695 // Since the pprof service enables sensitive/vulnerable behavior, this allows a user 696 // to enable a public-OK metrics endpoint without having to worry about ALSO exposing 697 // other profiling behavior or information. 698 MetricsHTTPFlag = cli.StringFlag{ 699 Name: "metrics.addr", 700 Usage: "Enable stand-alone metrics HTTP server listening interface", 701 Value: metrics.DefaultConfig.HTTP, 702 } 703 MetricsPortFlag = cli.IntFlag{ 704 Name: "metrics.port", 705 Usage: "Metrics HTTP server listening port", 706 Value: metrics.DefaultConfig.Port, 707 } 708 MetricsEnableInfluxDBFlag = cli.BoolFlag{ 709 Name: "metrics.influxdb", 710 Usage: "Enable metrics export/push to an external InfluxDB database", 711 } 712 MetricsInfluxDBEndpointFlag = cli.StringFlag{ 713 Name: "metrics.influxdb.endpoint", 714 Usage: "InfluxDB API endpoint to report metrics to", 715 Value: metrics.DefaultConfig.InfluxDBEndpoint, 716 } 717 MetricsInfluxDBDatabaseFlag = cli.StringFlag{ 718 Name: "metrics.influxdb.database", 719 Usage: "InfluxDB database name to push reported metrics to", 720 Value: metrics.DefaultConfig.InfluxDBDatabase, 721 } 722 MetricsInfluxDBUsernameFlag = cli.StringFlag{ 723 Name: "metrics.influxdb.username", 724 Usage: "Username to authorize access to the database", 725 Value: metrics.DefaultConfig.InfluxDBUsername, 726 } 727 MetricsInfluxDBPasswordFlag = cli.StringFlag{ 728 Name: "metrics.influxdb.password", 729 Usage: "Password to authorize access to the database", 730 Value: metrics.DefaultConfig.InfluxDBPassword, 731 } 732 // Tags are part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB. 733 // For example `host` tag could be used so that we can group all nodes and average a measurement 734 // across all of them, but also so that we can select a specific node and inspect its measurements. 735 // https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key 736 MetricsInfluxDBTagsFlag = cli.StringFlag{ 737 Name: "metrics.influxdb.tags", 738 Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements", 739 Value: metrics.DefaultConfig.InfluxDBTags, 740 } 741 EWASMInterpreterFlag = cli.StringFlag{ 742 Name: "vm.ewasm", 743 Usage: "External ewasm configuration (default = built-in interpreter)", 744 Value: "", 745 } 746 EVMInterpreterFlag = cli.StringFlag{ 747 Name: "vm.evm", 748 Usage: "External EVM configuration (default = built-in interpreter)", 749 Value: "", 750 } 751 ) 752 753 // MakeDataDir retrieves the currently requested data directory, terminating 754 // if none (or the empty string) is specified. If the node is starting a testnet, 755 // then a subdirectory of the specified datadir will be used. 756 func MakeDataDir(ctx *cli.Context) string { 757 if path := ctx.GlobalString(DataDirFlag.Name); path != "" { 758 if ctx.GlobalBool(LegacyTestnetFlag.Name) || ctx.GlobalBool(RopstenFlag.Name) { 759 // Maintain compatibility with older Geth configurations storing the 760 // Ropsten database in `testnet` instead of `ropsten`. 761 legacyPath := filepath.Join(path, "testnet") 762 if _, err := os.Stat(legacyPath); !os.IsNotExist(err) { 763 return legacyPath 764 } 765 return filepath.Join(path, "ropsten") 766 } 767 if ctx.GlobalBool(RinkebyFlag.Name) { 768 return filepath.Join(path, "rinkeby") 769 } 770 if ctx.GlobalBool(GoerliFlag.Name) { 771 return filepath.Join(path, "goerli") 772 } 773 if ctx.GlobalBool(YoloV3Flag.Name) { 774 return filepath.Join(path, "yolo-v3") 775 } 776 return path 777 } 778 Fatalf("Cannot determine default data directory, please set manually (--datadir)") 779 return "" 780 } 781 782 // setNodeKey creates a node key from set command line flags, either loading it 783 // from a file or as a specified hex value. If neither flags were provided, this 784 // method returns nil and an emphemeral key is to be generated. 785 func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { 786 var ( 787 hex = ctx.GlobalString(NodeKeyHexFlag.Name) 788 file = ctx.GlobalString(NodeKeyFileFlag.Name) 789 key *ecdsa.PrivateKey 790 err error 791 ) 792 switch { 793 case file != "" && hex != "": 794 Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) 795 case file != "": 796 if key, err = crypto.LoadECDSA(file); err != nil { 797 Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) 798 } 799 cfg.PrivateKey = key 800 case hex != "": 801 if key, err = crypto.HexToECDSA(hex); err != nil { 802 Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) 803 } 804 cfg.PrivateKey = key 805 } 806 } 807 808 // setNodeUserIdent creates the user identifier from CLI flags. 809 func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { 810 if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 { 811 cfg.UserIdent = identity 812 } 813 } 814 815 // setBootstrapNodes creates a list of bootstrap nodes from the command line 816 // flags, reverting to pre-configured ones if none have been specified. 817 func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { 818 urls := params.MainnetBootnodes 819 switch { 820 case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(LegacyBootnodesV4Flag.Name): 821 if ctx.GlobalIsSet(LegacyBootnodesV4Flag.Name) { 822 urls = SplitAndTrim(ctx.GlobalString(LegacyBootnodesV4Flag.Name)) 823 } else { 824 urls = SplitAndTrim(ctx.GlobalString(BootnodesFlag.Name)) 825 } 826 case ctx.GlobalBool(LegacyTestnetFlag.Name) || ctx.GlobalBool(RopstenFlag.Name): 827 urls = params.RopstenBootnodes 828 case ctx.GlobalBool(RinkebyFlag.Name): 829 urls = params.RinkebyBootnodes 830 case ctx.GlobalBool(GoerliFlag.Name): 831 urls = params.GoerliBootnodes 832 case ctx.GlobalBool(YoloV3Flag.Name): 833 urls = params.YoloV3Bootnodes 834 case cfg.BootstrapNodes != nil: 835 return // already set, don't apply defaults. 836 } 837 838 cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls)) 839 for _, url := range urls { 840 if url != "" { 841 node, err := enode.Parse(enode.ValidSchemes, url) 842 if err != nil { 843 log.Crit("Bootstrap URL invalid", "enode", url, "err", err) 844 continue 845 } 846 cfg.BootstrapNodes = append(cfg.BootstrapNodes, node) 847 } 848 } 849 } 850 851 // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line 852 // flags, reverting to pre-configured ones if none have been specified. 853 func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) { 854 urls := params.V5Bootnodes 855 switch { 856 case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(LegacyBootnodesV5Flag.Name): 857 if ctx.GlobalIsSet(LegacyBootnodesV5Flag.Name) { 858 urls = SplitAndTrim(ctx.GlobalString(LegacyBootnodesV5Flag.Name)) 859 } else { 860 urls = SplitAndTrim(ctx.GlobalString(BootnodesFlag.Name)) 861 } 862 case cfg.BootstrapNodesV5 != nil: 863 return // already set, don't apply defaults. 864 } 865 866 cfg.BootstrapNodesV5 = make([]*enode.Node, 0, len(urls)) 867 for _, url := range urls { 868 if url != "" { 869 node, err := enode.Parse(enode.ValidSchemes, url) 870 if err != nil { 871 log.Error("Bootstrap URL invalid", "enode", url, "err", err) 872 continue 873 } 874 cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node) 875 } 876 } 877 } 878 879 // setListenAddress creates a TCP listening address string from set command 880 // line flags. 881 func setListenAddress(ctx *cli.Context, cfg *p2p.Config) { 882 if ctx.GlobalIsSet(ListenPortFlag.Name) { 883 cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)) 884 } 885 } 886 887 // setNAT creates a port mapper from command line flags. 888 func setNAT(ctx *cli.Context, cfg *p2p.Config) { 889 if ctx.GlobalIsSet(NATFlag.Name) { 890 natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name)) 891 if err != nil { 892 Fatalf("Option %s: %v", NATFlag.Name, err) 893 } 894 cfg.NAT = natif 895 } 896 } 897 898 // SplitAndTrim splits input separated by a comma 899 // and trims excessive white space from the substrings. 900 func SplitAndTrim(input string) (ret []string) { 901 l := strings.Split(input, ",") 902 for _, r := range l { 903 if r = strings.TrimSpace(r); r != "" { 904 ret = append(ret, r) 905 } 906 } 907 return ret 908 } 909 910 // setHTTP creates the HTTP RPC listener interface string from the set 911 // command line flags, returning empty if the HTTP endpoint is disabled. 912 func setHTTP(ctx *cli.Context, cfg *node.Config) { 913 if ctx.GlobalBool(LegacyRPCEnabledFlag.Name) && cfg.HTTPHost == "" { 914 log.Warn("The flag --rpc is deprecated and will be removed in the future, please use --http") 915 cfg.HTTPHost = "127.0.0.1" 916 if ctx.GlobalIsSet(LegacyRPCListenAddrFlag.Name) { 917 cfg.HTTPHost = ctx.GlobalString(LegacyRPCListenAddrFlag.Name) 918 log.Warn("The flag --rpcaddr is deprecated and will be removed in the future, please use --http.addr") 919 } 920 } 921 if ctx.GlobalBool(HTTPEnabledFlag.Name) && cfg.HTTPHost == "" { 922 cfg.HTTPHost = "127.0.0.1" 923 if ctx.GlobalIsSet(HTTPListenAddrFlag.Name) { 924 cfg.HTTPHost = ctx.GlobalString(HTTPListenAddrFlag.Name) 925 } 926 } 927 928 if ctx.GlobalIsSet(LegacyRPCPortFlag.Name) { 929 cfg.HTTPPort = ctx.GlobalInt(LegacyRPCPortFlag.Name) 930 log.Warn("The flag --rpcport is deprecated and will be removed in the future, please use --http.port") 931 } 932 if ctx.GlobalIsSet(HTTPPortFlag.Name) { 933 cfg.HTTPPort = ctx.GlobalInt(HTTPPortFlag.Name) 934 } 935 936 if ctx.GlobalIsSet(LegacyRPCCORSDomainFlag.Name) { 937 cfg.HTTPCors = SplitAndTrim(ctx.GlobalString(LegacyRPCCORSDomainFlag.Name)) 938 log.Warn("The flag --rpccorsdomain is deprecated and will be removed in the future, please use --http.corsdomain") 939 } 940 if ctx.GlobalIsSet(HTTPCORSDomainFlag.Name) { 941 cfg.HTTPCors = SplitAndTrim(ctx.GlobalString(HTTPCORSDomainFlag.Name)) 942 } 943 944 if ctx.GlobalIsSet(LegacyRPCApiFlag.Name) { 945 cfg.HTTPModules = SplitAndTrim(ctx.GlobalString(LegacyRPCApiFlag.Name)) 946 log.Warn("The flag --rpcapi is deprecated and will be removed in the future, please use --http.api") 947 } 948 if ctx.GlobalIsSet(HTTPApiFlag.Name) { 949 cfg.HTTPModules = SplitAndTrim(ctx.GlobalString(HTTPApiFlag.Name)) 950 } 951 952 if ctx.GlobalIsSet(LegacyRPCVirtualHostsFlag.Name) { 953 cfg.HTTPVirtualHosts = SplitAndTrim(ctx.GlobalString(LegacyRPCVirtualHostsFlag.Name)) 954 log.Warn("The flag --rpcvhosts is deprecated and will be removed in the future, please use --http.vhosts") 955 } 956 if ctx.GlobalIsSet(HTTPVirtualHostsFlag.Name) { 957 cfg.HTTPVirtualHosts = SplitAndTrim(ctx.GlobalString(HTTPVirtualHostsFlag.Name)) 958 } 959 960 if ctx.GlobalIsSet(HTTPPathPrefixFlag.Name) { 961 cfg.HTTPPathPrefix = ctx.GlobalString(HTTPPathPrefixFlag.Name) 962 } 963 } 964 965 // setGraphQL creates the GraphQL listener interface string from the set 966 // command line flags, returning empty if the GraphQL endpoint is disabled. 967 func setGraphQL(ctx *cli.Context, cfg *node.Config) { 968 if ctx.GlobalIsSet(GraphQLCORSDomainFlag.Name) { 969 cfg.GraphQLCors = SplitAndTrim(ctx.GlobalString(GraphQLCORSDomainFlag.Name)) 970 } 971 if ctx.GlobalIsSet(GraphQLVirtualHostsFlag.Name) { 972 cfg.GraphQLVirtualHosts = SplitAndTrim(ctx.GlobalString(GraphQLVirtualHostsFlag.Name)) 973 } 974 } 975 976 // setWS creates the WebSocket RPC listener interface string from the set 977 // command line flags, returning empty if the HTTP endpoint is disabled. 978 func setWS(ctx *cli.Context, cfg *node.Config) { 979 if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" { 980 cfg.WSHost = "127.0.0.1" 981 if ctx.GlobalIsSet(LegacyWSListenAddrFlag.Name) { 982 cfg.WSHost = ctx.GlobalString(LegacyWSListenAddrFlag.Name) 983 log.Warn("The flag --wsaddr is deprecated and will be removed in the future, please use --ws.addr") 984 } 985 if ctx.GlobalIsSet(WSListenAddrFlag.Name) { 986 cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name) 987 } 988 } 989 if ctx.GlobalIsSet(LegacyWSPortFlag.Name) { 990 cfg.WSPort = ctx.GlobalInt(LegacyWSPortFlag.Name) 991 log.Warn("The flag --wsport is deprecated and will be removed in the future, please use --ws.port") 992 } 993 if ctx.GlobalIsSet(WSPortFlag.Name) { 994 cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name) 995 } 996 997 if ctx.GlobalIsSet(LegacyWSAllowedOriginsFlag.Name) { 998 cfg.WSOrigins = SplitAndTrim(ctx.GlobalString(LegacyWSAllowedOriginsFlag.Name)) 999 log.Warn("The flag --wsorigins is deprecated and will be removed in the future, please use --ws.origins") 1000 } 1001 if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) { 1002 cfg.WSOrigins = SplitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name)) 1003 } 1004 1005 if ctx.GlobalIsSet(LegacyWSApiFlag.Name) { 1006 cfg.WSModules = SplitAndTrim(ctx.GlobalString(LegacyWSApiFlag.Name)) 1007 log.Warn("The flag --wsapi is deprecated and will be removed in the future, please use --ws.api") 1008 } 1009 if ctx.GlobalIsSet(WSApiFlag.Name) { 1010 cfg.WSModules = SplitAndTrim(ctx.GlobalString(WSApiFlag.Name)) 1011 } 1012 1013 if ctx.GlobalIsSet(WSPathPrefixFlag.Name) { 1014 cfg.WSPathPrefix = ctx.GlobalString(WSPathPrefixFlag.Name) 1015 } 1016 } 1017 1018 // setIPC creates an IPC path configuration from the set command line flags, 1019 // returning an empty string if IPC was explicitly disabled, or the set path. 1020 func setIPC(ctx *cli.Context, cfg *node.Config) { 1021 CheckExclusive(ctx, IPCDisabledFlag, IPCPathFlag) 1022 switch { 1023 case ctx.GlobalBool(IPCDisabledFlag.Name): 1024 cfg.IPCPath = "" 1025 case ctx.GlobalIsSet(IPCPathFlag.Name): 1026 cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name) 1027 } 1028 } 1029 1030 // setLes configures the les server and ultra light client settings from the command line flags. 1031 func setLes(ctx *cli.Context, cfg *eth.Config) { 1032 if ctx.GlobalIsSet(LegacyLightServFlag.Name) { 1033 cfg.LightServ = ctx.GlobalInt(LegacyLightServFlag.Name) 1034 log.Warn("The flag --lightserv is deprecated and will be removed in the future, please use --light.serve") 1035 } 1036 if ctx.GlobalIsSet(LightServeFlag.Name) { 1037 cfg.LightServ = ctx.GlobalInt(LightServeFlag.Name) 1038 } 1039 if ctx.GlobalIsSet(LightIngressFlag.Name) { 1040 cfg.LightIngress = ctx.GlobalInt(LightIngressFlag.Name) 1041 } 1042 if ctx.GlobalIsSet(LightEgressFlag.Name) { 1043 cfg.LightEgress = ctx.GlobalInt(LightEgressFlag.Name) 1044 } 1045 if ctx.GlobalIsSet(LegacyLightPeersFlag.Name) { 1046 cfg.LightPeers = ctx.GlobalInt(LegacyLightPeersFlag.Name) 1047 log.Warn("The flag --lightpeers is deprecated and will be removed in the future, please use --light.maxpeers") 1048 } 1049 if ctx.GlobalIsSet(LightMaxPeersFlag.Name) { 1050 cfg.LightPeers = ctx.GlobalInt(LightMaxPeersFlag.Name) 1051 } 1052 if ctx.GlobalIsSet(UltraLightServersFlag.Name) { 1053 cfg.UltraLightServers = strings.Split(ctx.GlobalString(UltraLightServersFlag.Name), ",") 1054 } 1055 if ctx.GlobalIsSet(UltraLightFractionFlag.Name) { 1056 cfg.UltraLightFraction = ctx.GlobalInt(UltraLightFractionFlag.Name) 1057 } 1058 if cfg.UltraLightFraction <= 0 && cfg.UltraLightFraction > 100 { 1059 log.Error("Ultra light fraction is invalid", "had", cfg.UltraLightFraction, "updated", eth.DefaultConfig.UltraLightFraction) 1060 cfg.UltraLightFraction = eth.DefaultConfig.UltraLightFraction 1061 } 1062 if ctx.GlobalIsSet(UltraLightOnlyAnnounceFlag.Name) { 1063 cfg.UltraLightOnlyAnnounce = ctx.GlobalBool(UltraLightOnlyAnnounceFlag.Name) 1064 } 1065 if ctx.GlobalIsSet(LightNoPruneFlag.Name) { 1066 cfg.LightNoPrune = ctx.GlobalBool(LightNoPruneFlag.Name) 1067 } 1068 } 1069 1070 // makeDatabaseHandles raises out the number of allowed file handles per process 1071 // for Geth and returns half of the allowance to assign to the database. 1072 func makeDatabaseHandles() int { 1073 limit, err := fdlimit.Maximum() 1074 if err != nil { 1075 Fatalf("Failed to retrieve file descriptor allowance: %v", err) 1076 } 1077 raised, err := fdlimit.Raise(uint64(limit)) 1078 if err != nil { 1079 Fatalf("Failed to raise file descriptor allowance: %v", err) 1080 } 1081 return int(raised / 2) // Leave half for networking and other stuff 1082 } 1083 1084 // MakeAddress converts an account specified directly as a hex encoded string or 1085 // a key index in the key store to an internal account representation. 1086 func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) { 1087 // If the specified account is a valid address, return it 1088 if common.IsHexAddress(account) { 1089 return accounts.Account{Address: common.HexToAddress(account)}, nil 1090 } 1091 // Otherwise try to interpret the account as a keystore index 1092 index, err := strconv.Atoi(account) 1093 if err != nil || index < 0 { 1094 return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account) 1095 } 1096 log.Warn("-------------------------------------------------------------------") 1097 log.Warn("Referring to accounts by order in the keystore folder is dangerous!") 1098 log.Warn("This functionality is deprecated and will be removed in the future!") 1099 log.Warn("Please use explicit addresses! (can search via `geth account list`)") 1100 log.Warn("-------------------------------------------------------------------") 1101 1102 accs := ks.Accounts() 1103 if len(accs) <= index { 1104 return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs)) 1105 } 1106 return accs[index], nil 1107 } 1108 1109 // setEtherbase retrieves the etherbase either from the directly specified 1110 // command line flags or from the keystore if CLI indexed. 1111 func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) { 1112 // Extract the current etherbase, new flag overriding legacy one 1113 var etherbase string 1114 if ctx.GlobalIsSet(LegacyMinerEtherbaseFlag.Name) { 1115 etherbase = ctx.GlobalString(LegacyMinerEtherbaseFlag.Name) 1116 log.Warn("The flag --etherbase is deprecated and will be removed in the future, please use --miner.etherbase") 1117 1118 } 1119 if ctx.GlobalIsSet(MinerEtherbaseFlag.Name) { 1120 etherbase = ctx.GlobalString(MinerEtherbaseFlag.Name) 1121 } 1122 // Convert the etherbase into an address and configure it 1123 if etherbase != "" { 1124 if ks != nil { 1125 account, err := MakeAddress(ks, etherbase) 1126 if err != nil { 1127 Fatalf("Invalid miner etherbase: %v", err) 1128 } 1129 cfg.Miner.Etherbase = account.Address 1130 } else { 1131 Fatalf("No etherbase configured") 1132 } 1133 } 1134 } 1135 1136 // MakePasswordList reads password lines from the file specified by the global --password flag. 1137 func MakePasswordList(ctx *cli.Context) []string { 1138 path := ctx.GlobalString(PasswordFileFlag.Name) 1139 if path == "" { 1140 return nil 1141 } 1142 text, err := ioutil.ReadFile(path) 1143 if err != nil { 1144 Fatalf("Failed to read password file: %v", err) 1145 } 1146 lines := strings.Split(string(text), "\n") 1147 // Sanitise DOS line endings. 1148 for i := range lines { 1149 lines[i] = strings.TrimRight(lines[i], "\r") 1150 } 1151 return lines 1152 } 1153 1154 func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { 1155 setNodeKey(ctx, cfg) 1156 setNAT(ctx, cfg) 1157 setListenAddress(ctx, cfg) 1158 setBootstrapNodes(ctx, cfg) 1159 setBootstrapNodesV5(ctx, cfg) 1160 1161 lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light" 1162 lightServer := (ctx.GlobalInt(LegacyLightServFlag.Name) != 0 || ctx.GlobalInt(LightServeFlag.Name) != 0) 1163 1164 lightPeers := ctx.GlobalInt(LegacyLightPeersFlag.Name) 1165 if ctx.GlobalIsSet(LightMaxPeersFlag.Name) { 1166 lightPeers = ctx.GlobalInt(LightMaxPeersFlag.Name) 1167 } 1168 if lightClient && !ctx.GlobalIsSet(LegacyLightPeersFlag.Name) && !ctx.GlobalIsSet(LightMaxPeersFlag.Name) { 1169 // dynamic default - for clients we use 1/10th of the default for servers 1170 lightPeers /= 10 1171 } 1172 1173 if ctx.GlobalIsSet(MaxPeersFlag.Name) { 1174 cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) 1175 if lightServer && !ctx.GlobalIsSet(LegacyLightPeersFlag.Name) && !ctx.GlobalIsSet(LightMaxPeersFlag.Name) { 1176 cfg.MaxPeers += lightPeers 1177 } 1178 } else { 1179 if lightServer { 1180 cfg.MaxPeers += lightPeers 1181 } 1182 if lightClient && (ctx.GlobalIsSet(LegacyLightPeersFlag.Name) || ctx.GlobalIsSet(LightMaxPeersFlag.Name)) && cfg.MaxPeers < lightPeers { 1183 cfg.MaxPeers = lightPeers 1184 } 1185 } 1186 if !(lightClient || lightServer) { 1187 lightPeers = 0 1188 } 1189 ethPeers := cfg.MaxPeers - lightPeers 1190 if lightClient { 1191 ethPeers = 0 1192 } 1193 log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers) 1194 1195 if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) { 1196 cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name) 1197 } 1198 if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient { 1199 cfg.NoDiscovery = true 1200 } 1201 1202 // if we're running a light client or server, force enable the v5 peer discovery 1203 // unless it is explicitly disabled with --nodiscover note that explicitly specifying 1204 // --v5disc overrides --nodiscover, in which case the later only disables v4 discovery 1205 forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name) 1206 if ctx.GlobalIsSet(DiscoveryV5Flag.Name) { 1207 cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name) 1208 } else if forceV5Discovery { 1209 cfg.DiscoveryV5 = true 1210 } 1211 1212 if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" { 1213 list, err := netutil.ParseNetlist(netrestrict) 1214 if err != nil { 1215 Fatalf("Option %q: %v", NetrestrictFlag.Name, err) 1216 } 1217 cfg.NetRestrict = list 1218 } 1219 1220 if ctx.GlobalBool(DeveloperFlag.Name) { 1221 // --dev mode can't use p2p networking. 1222 cfg.MaxPeers = 0 1223 cfg.ListenAddr = ":0" 1224 cfg.NoDiscovery = true 1225 cfg.DiscoveryV5 = false 1226 } 1227 } 1228 1229 // SetNodeConfig applies node-related command line flags to the config. 1230 func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { 1231 SetP2PConfig(ctx, &cfg.P2P) 1232 setIPC(ctx, cfg) 1233 setHTTP(ctx, cfg) 1234 setGraphQL(ctx, cfg) 1235 setWS(ctx, cfg) 1236 setNodeUserIdent(ctx, cfg) 1237 setDataDir(ctx, cfg) 1238 setSmartCard(ctx, cfg) 1239 1240 if ctx.GlobalIsSet(ExternalSignerFlag.Name) { 1241 cfg.ExternalSigner = ctx.GlobalString(ExternalSignerFlag.Name) 1242 } 1243 1244 if ctx.GlobalIsSet(KeyStoreDirFlag.Name) { 1245 cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name) 1246 } 1247 if ctx.GlobalIsSet(LightKDFFlag.Name) { 1248 cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name) 1249 } 1250 if ctx.GlobalIsSet(NoUSBFlag.Name) || cfg.NoUSB { 1251 log.Warn("Option nousb is deprecated and USB is deactivated by default. Use --usb to enable") 1252 } 1253 if ctx.GlobalIsSet(USBFlag.Name) { 1254 cfg.USB = ctx.GlobalBool(USBFlag.Name) 1255 } 1256 if ctx.GlobalIsSet(InsecureUnlockAllowedFlag.Name) { 1257 cfg.InsecureUnlockAllowed = ctx.GlobalBool(InsecureUnlockAllowedFlag.Name) 1258 } 1259 } 1260 1261 func setSmartCard(ctx *cli.Context, cfg *node.Config) { 1262 // Skip enabling smartcards if no path is set 1263 path := ctx.GlobalString(SmartCardDaemonPathFlag.Name) 1264 if path == "" { 1265 return 1266 } 1267 // Sanity check that the smartcard path is valid 1268 fi, err := os.Stat(path) 1269 if err != nil { 1270 log.Info("Smartcard socket not found, disabling", "err", err) 1271 return 1272 } 1273 if fi.Mode()&os.ModeType != os.ModeSocket { 1274 log.Error("Invalid smartcard daemon path", "path", path, "type", fi.Mode().String()) 1275 return 1276 } 1277 // Smartcard daemon path exists and is a socket, enable it 1278 cfg.SmartCardDaemonPath = path 1279 } 1280 1281 func setDataDir(ctx *cli.Context, cfg *node.Config) { 1282 switch { 1283 case ctx.GlobalIsSet(DataDirFlag.Name): 1284 cfg.DataDir = ctx.GlobalString(DataDirFlag.Name) 1285 case ctx.GlobalBool(DeveloperFlag.Name): 1286 cfg.DataDir = "" // unless explicitly requested, use memory databases 1287 case (ctx.GlobalBool(LegacyTestnetFlag.Name) || ctx.GlobalBool(RopstenFlag.Name)) && cfg.DataDir == node.DefaultDataDir(): 1288 // Maintain compatibility with older Geth configurations storing the 1289 // Ropsten database in `testnet` instead of `ropsten`. 1290 legacyPath := filepath.Join(node.DefaultDataDir(), "testnet") 1291 if _, err := os.Stat(legacyPath); !os.IsNotExist(err) { 1292 log.Warn("Using the deprecated `testnet` datadir. Future versions will store the Ropsten chain in `ropsten`.") 1293 cfg.DataDir = legacyPath 1294 } else { 1295 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ropsten") 1296 } 1297 case ctx.GlobalBool(RinkebyFlag.Name) && cfg.DataDir == node.DefaultDataDir(): 1298 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby") 1299 case ctx.GlobalBool(GoerliFlag.Name) && cfg.DataDir == node.DefaultDataDir(): 1300 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli") 1301 case ctx.GlobalBool(YoloV3Flag.Name) && cfg.DataDir == node.DefaultDataDir(): 1302 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "yolo-v2") 1303 } 1304 } 1305 1306 func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) { 1307 // If we are running the light client, apply another group 1308 // settings for gas oracle. 1309 if light { 1310 cfg.Blocks = eth.DefaultLightGPOConfig.Blocks 1311 cfg.Percentile = eth.DefaultLightGPOConfig.Percentile 1312 } 1313 if ctx.GlobalIsSet(LegacyGpoBlocksFlag.Name) { 1314 cfg.Blocks = ctx.GlobalInt(LegacyGpoBlocksFlag.Name) 1315 log.Warn("The flag --gpoblocks is deprecated and will be removed in the future, please use --gpo.blocks") 1316 } 1317 if ctx.GlobalIsSet(GpoBlocksFlag.Name) { 1318 cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name) 1319 } 1320 if ctx.GlobalIsSet(LegacyGpoPercentileFlag.Name) { 1321 cfg.Percentile = ctx.GlobalInt(LegacyGpoPercentileFlag.Name) 1322 log.Warn("The flag --gpopercentile is deprecated and will be removed in the future, please use --gpo.percentile") 1323 } 1324 if ctx.GlobalIsSet(GpoPercentileFlag.Name) { 1325 cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name) 1326 } 1327 if ctx.GlobalIsSet(GpoMaxGasPriceFlag.Name) { 1328 cfg.MaxPrice = big.NewInt(ctx.GlobalInt64(GpoMaxGasPriceFlag.Name)) 1329 } 1330 } 1331 1332 func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) { 1333 if ctx.GlobalIsSet(TxPoolLocalsFlag.Name) { 1334 locals := strings.Split(ctx.GlobalString(TxPoolLocalsFlag.Name), ",") 1335 for _, account := range locals { 1336 if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) { 1337 Fatalf("Invalid account in --txpool.locals: %s", trimmed) 1338 } else { 1339 cfg.Locals = append(cfg.Locals, common.HexToAddress(account)) 1340 } 1341 } 1342 } 1343 if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) { 1344 cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name) 1345 } 1346 if ctx.GlobalIsSet(TxPoolJournalFlag.Name) { 1347 cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name) 1348 } 1349 if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) { 1350 cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name) 1351 } 1352 if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) { 1353 cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name) 1354 } 1355 if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) { 1356 cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name) 1357 } 1358 if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) { 1359 cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name) 1360 } 1361 if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) { 1362 cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name) 1363 } 1364 if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) { 1365 cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name) 1366 } 1367 if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) { 1368 cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name) 1369 } 1370 if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) { 1371 cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name) 1372 } 1373 } 1374 1375 func setEthash(ctx *cli.Context, cfg *eth.Config) { 1376 if ctx.GlobalIsSet(EthashCacheDirFlag.Name) { 1377 cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name) 1378 } 1379 if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) { 1380 cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name) 1381 } 1382 if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) { 1383 cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name) 1384 } 1385 if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) { 1386 cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name) 1387 } 1388 if ctx.GlobalIsSet(EthashCachesLockMmapFlag.Name) { 1389 cfg.Ethash.CachesLockMmap = ctx.GlobalBool(EthashCachesLockMmapFlag.Name) 1390 } 1391 if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) { 1392 cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name) 1393 } 1394 if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) { 1395 cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name) 1396 } 1397 if ctx.GlobalIsSet(EthashDatasetsLockMmapFlag.Name) { 1398 cfg.Ethash.DatasetsLockMmap = ctx.GlobalBool(EthashDatasetsLockMmapFlag.Name) 1399 } 1400 } 1401 1402 func setMiner(ctx *cli.Context, cfg *miner.Config) { 1403 if ctx.GlobalIsSet(MinerNotifyFlag.Name) { 1404 cfg.Notify = strings.Split(ctx.GlobalString(MinerNotifyFlag.Name), ",") 1405 } 1406 if ctx.GlobalIsSet(LegacyMinerExtraDataFlag.Name) { 1407 cfg.ExtraData = []byte(ctx.GlobalString(LegacyMinerExtraDataFlag.Name)) 1408 log.Warn("The flag --extradata is deprecated and will be removed in the future, please use --miner.extradata") 1409 } 1410 if ctx.GlobalIsSet(MinerExtraDataFlag.Name) { 1411 cfg.ExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name)) 1412 } 1413 if ctx.GlobalIsSet(LegacyMinerGasTargetFlag.Name) { 1414 cfg.GasFloor = ctx.GlobalUint64(LegacyMinerGasTargetFlag.Name) 1415 log.Warn("The flag --targetgaslimit is deprecated and will be removed in the future, please use --miner.gastarget") 1416 } 1417 if ctx.GlobalIsSet(MinerGasTargetFlag.Name) { 1418 cfg.GasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name) 1419 } 1420 if ctx.GlobalIsSet(MinerGasLimitFlag.Name) { 1421 cfg.GasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name) 1422 } 1423 if ctx.GlobalIsSet(LegacyMinerGasPriceFlag.Name) { 1424 cfg.GasPrice = GlobalBig(ctx, LegacyMinerGasPriceFlag.Name) 1425 log.Warn("The flag --gasprice is deprecated and will be removed in the future, please use --miner.gasprice") 1426 } 1427 if ctx.GlobalIsSet(MinerGasPriceFlag.Name) { 1428 cfg.GasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name) 1429 } 1430 if ctx.GlobalIsSet(MinerRecommitIntervalFlag.Name) { 1431 cfg.Recommit = ctx.GlobalDuration(MinerRecommitIntervalFlag.Name) 1432 } 1433 if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) { 1434 cfg.Noverify = ctx.GlobalBool(MinerNoVerfiyFlag.Name) 1435 } 1436 } 1437 1438 func setWhitelist(ctx *cli.Context, cfg *eth.Config) { 1439 whitelist := ctx.GlobalString(WhitelistFlag.Name) 1440 if whitelist == "" { 1441 return 1442 } 1443 cfg.Whitelist = make(map[uint64]common.Hash) 1444 for _, entry := range strings.Split(whitelist, ",") { 1445 parts := strings.Split(entry, "=") 1446 if len(parts) != 2 { 1447 Fatalf("Invalid whitelist entry: %s", entry) 1448 } 1449 number, err := strconv.ParseUint(parts[0], 0, 64) 1450 if err != nil { 1451 Fatalf("Invalid whitelist block number %s: %v", parts[0], err) 1452 } 1453 var hash common.Hash 1454 if err = hash.UnmarshalText([]byte(parts[1])); err != nil { 1455 Fatalf("Invalid whitelist hash %s: %v", parts[1], err) 1456 } 1457 cfg.Whitelist[number] = hash 1458 } 1459 } 1460 1461 // CheckExclusive verifies that only a single instance of the provided flags was 1462 // set by the user. Each flag might optionally be followed by a string type to 1463 // specialize it further. 1464 func CheckExclusive(ctx *cli.Context, args ...interface{}) { 1465 set := make([]string, 0, 1) 1466 for i := 0; i < len(args); i++ { 1467 // Make sure the next argument is a flag and skip if not set 1468 flag, ok := args[i].(cli.Flag) 1469 if !ok { 1470 panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i])) 1471 } 1472 // Check if next arg extends current and expand its name if so 1473 name := flag.GetName() 1474 1475 if i+1 < len(args) { 1476 switch option := args[i+1].(type) { 1477 case string: 1478 // Extended flag check, make sure value set doesn't conflict with passed in option 1479 if ctx.GlobalString(flag.GetName()) == option { 1480 name += "=" + option 1481 set = append(set, "--"+name) 1482 } 1483 // shift arguments and continue 1484 i++ 1485 continue 1486 1487 case cli.Flag: 1488 default: 1489 panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1])) 1490 } 1491 } 1492 // Mark the flag if it's set 1493 if ctx.GlobalIsSet(flag.GetName()) { 1494 set = append(set, "--"+name) 1495 } 1496 } 1497 if len(set) > 1 { 1498 Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", ")) 1499 } 1500 } 1501 1502 // SetShhConfig applies shh-related command line flags to the config. 1503 func SetShhConfig(ctx *cli.Context, stack *node.Node) { 1504 if ctx.GlobalIsSet(WhisperEnabledFlag.Name) || 1505 ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) || 1506 ctx.GlobalIsSet(WhisperMinPOWFlag.Name) || 1507 ctx.GlobalIsSet(WhisperRestrictConnectionBetweenLightClientsFlag.Name) { 1508 log.Warn("Whisper support has been deprecated and the code has been moved to github.com/ethereum/whisper") 1509 } 1510 } 1511 1512 // SetEthConfig applies eth-related command line flags to the config. 1513 func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { 1514 // Avoid conflicting network flags 1515 CheckExclusive(ctx, MainnetFlag, DeveloperFlag, LegacyTestnetFlag, RopstenFlag, RinkebyFlag, GoerliFlag, YoloV3Flag) 1516 CheckExclusive(ctx, LegacyLightServFlag, LightServeFlag, SyncModeFlag, "light") 1517 CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer 1518 CheckExclusive(ctx, GCModeFlag, "archive", TxLookupLimitFlag) 1519 if (ctx.GlobalIsSet(LegacyLightServFlag.Name) || ctx.GlobalIsSet(LightServeFlag.Name)) && ctx.GlobalIsSet(TxLookupLimitFlag.Name) { 1520 log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited") 1521 } 1522 var ks *keystore.KeyStore 1523 if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 { 1524 ks = keystores[0].(*keystore.KeyStore) 1525 } 1526 setEtherbase(ctx, ks, cfg) 1527 setGPO(ctx, &cfg.GPO, ctx.GlobalString(SyncModeFlag.Name) == "light") 1528 setTxPool(ctx, &cfg.TxPool) 1529 setEthash(ctx, cfg) 1530 setMiner(ctx, &cfg.Miner) 1531 setWhitelist(ctx, cfg) 1532 setLes(ctx, cfg) 1533 1534 if ctx.GlobalIsSet(SyncModeFlag.Name) { 1535 cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) 1536 } 1537 if ctx.GlobalIsSet(NetworkIdFlag.Name) { 1538 cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name) 1539 } 1540 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) { 1541 cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 1542 } 1543 cfg.DatabaseHandles = makeDatabaseHandles() 1544 if ctx.GlobalIsSet(AncientFlag.Name) { 1545 cfg.DatabaseFreezer = ctx.GlobalString(AncientFlag.Name) 1546 } 1547 1548 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 1549 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 1550 } 1551 if ctx.GlobalIsSet(GCModeFlag.Name) { 1552 cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive" 1553 } 1554 if ctx.GlobalIsSet(CacheNoPrefetchFlag.Name) { 1555 cfg.NoPrefetch = ctx.GlobalBool(CacheNoPrefetchFlag.Name) 1556 } 1557 // Read the value from the flag no matter if it's set or not. 1558 cfg.Preimages = ctx.GlobalBool(CachePreimagesFlag.Name) 1559 if cfg.NoPruning && !cfg.Preimages { 1560 cfg.Preimages = true 1561 log.Info("Enabling recording of key preimages since archive mode is used") 1562 } 1563 if ctx.GlobalIsSet(TxLookupLimitFlag.Name) { 1564 cfg.TxLookupLimit = ctx.GlobalUint64(TxLookupLimitFlag.Name) 1565 } 1566 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) { 1567 cfg.TrieCleanCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100 1568 } 1569 if ctx.GlobalIsSet(CacheTrieJournalFlag.Name) { 1570 cfg.TrieCleanCacheJournal = ctx.GlobalString(CacheTrieJournalFlag.Name) 1571 } 1572 if ctx.GlobalIsSet(CacheTrieRejournalFlag.Name) { 1573 cfg.TrieCleanCacheRejournal = ctx.GlobalDuration(CacheTrieRejournalFlag.Name) 1574 } 1575 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 1576 cfg.TrieDirtyCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 1577 } 1578 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheSnapshotFlag.Name) { 1579 cfg.SnapshotCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheSnapshotFlag.Name) / 100 1580 } 1581 if !ctx.GlobalIsSet(SnapshotFlag.Name) { 1582 // If snap-sync is requested, this flag is also required 1583 if cfg.SyncMode == downloader.SnapSync { 1584 log.Info("Snap sync requested, enabling --snapshot") 1585 } else { 1586 cfg.TrieCleanCache += cfg.SnapshotCache 1587 cfg.SnapshotCache = 0 // Disabled 1588 } 1589 } 1590 if ctx.GlobalIsSet(DocRootFlag.Name) { 1591 cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name) 1592 } 1593 if ctx.GlobalIsSet(VMEnableDebugFlag.Name) { 1594 // TODO(fjl): force-enable this in --dev mode 1595 cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name) 1596 } 1597 1598 if ctx.GlobalIsSet(EWASMInterpreterFlag.Name) { 1599 cfg.EWASMInterpreter = ctx.GlobalString(EWASMInterpreterFlag.Name) 1600 } 1601 1602 if ctx.GlobalIsSet(EVMInterpreterFlag.Name) { 1603 cfg.EVMInterpreter = ctx.GlobalString(EVMInterpreterFlag.Name) 1604 } 1605 if ctx.GlobalIsSet(RPCGlobalGasCapFlag.Name) { 1606 cfg.RPCGasCap = ctx.GlobalUint64(RPCGlobalGasCapFlag.Name) 1607 } 1608 if cfg.RPCGasCap != 0 { 1609 log.Info("Set global gas cap", "cap", cfg.RPCGasCap) 1610 } else { 1611 log.Info("Global gas cap disabled") 1612 } 1613 if ctx.GlobalIsSet(RPCGlobalTxFeeCapFlag.Name) { 1614 cfg.RPCTxFeeCap = ctx.GlobalFloat64(RPCGlobalTxFeeCapFlag.Name) 1615 } 1616 if ctx.GlobalIsSet(NoDiscoverFlag.Name) { 1617 cfg.EthDiscoveryURLs, cfg.SnapDiscoveryURLs = []string{}, []string{} 1618 } else if ctx.GlobalIsSet(DNSDiscoveryFlag.Name) { 1619 urls := ctx.GlobalString(DNSDiscoveryFlag.Name) 1620 if urls == "" { 1621 cfg.EthDiscoveryURLs = []string{} 1622 } else { 1623 cfg.EthDiscoveryURLs = SplitAndTrim(urls) 1624 } 1625 } 1626 // Override any default configs for hard coded networks. 1627 switch { 1628 case ctx.GlobalBool(MainnetFlag.Name): 1629 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1630 cfg.NetworkId = 1 1631 } 1632 cfg.Genesis = core.DefaultGenesisBlock() 1633 SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash) 1634 case ctx.GlobalBool(LegacyTestnetFlag.Name) || ctx.GlobalBool(RopstenFlag.Name): 1635 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1636 cfg.NetworkId = 3 1637 } 1638 cfg.Genesis = core.DefaultRopstenGenesisBlock() 1639 SetDNSDiscoveryDefaults(cfg, params.RopstenGenesisHash) 1640 case ctx.GlobalBool(RinkebyFlag.Name): 1641 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1642 cfg.NetworkId = 4 1643 } 1644 cfg.Genesis = core.DefaultRinkebyGenesisBlock() 1645 SetDNSDiscoveryDefaults(cfg, params.RinkebyGenesisHash) 1646 case ctx.GlobalBool(GoerliFlag.Name): 1647 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1648 cfg.NetworkId = 5 1649 } 1650 cfg.Genesis = core.DefaultGoerliGenesisBlock() 1651 SetDNSDiscoveryDefaults(cfg, params.GoerliGenesisHash) 1652 case ctx.GlobalBool(YoloV3Flag.Name): 1653 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1654 cfg.NetworkId = new(big.Int).SetBytes([]byte("yolov3")).Uint64() // "yolov3" 1655 } 1656 cfg.Genesis = core.DefaultYoloV3GenesisBlock() 1657 case ctx.GlobalBool(DeveloperFlag.Name): 1658 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1659 cfg.NetworkId = 1337 1660 } 1661 // Create new developer account or reuse existing one 1662 var ( 1663 developer accounts.Account 1664 passphrase string 1665 err error 1666 ) 1667 if list := MakePasswordList(ctx); len(list) > 0 { 1668 // Just take the first value. Although the function returns a possible multiple values and 1669 // some usages iterate through them as attempts, that doesn't make sense in this setting, 1670 // when we're definitely concerned with only one account. 1671 passphrase = list[0] 1672 } 1673 // setEtherbase has been called above, configuring the miner address from command line flags. 1674 if cfg.Miner.Etherbase != (common.Address{}) { 1675 developer = accounts.Account{Address: cfg.Miner.Etherbase} 1676 } else if accs := ks.Accounts(); len(accs) > 0 { 1677 developer = ks.Accounts()[0] 1678 } else { 1679 developer, err = ks.NewAccount(passphrase) 1680 if err != nil { 1681 Fatalf("Failed to create developer account: %v", err) 1682 } 1683 } 1684 if err := ks.Unlock(developer, passphrase); err != nil { 1685 Fatalf("Failed to unlock developer account: %v", err) 1686 } 1687 log.Info("Using developer account", "address", developer.Address) 1688 1689 // Create a new developer genesis block or reuse existing one 1690 cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address) 1691 if ctx.GlobalIsSet(DataDirFlag.Name) { 1692 // Check if we have an already initialized chain and fall back to 1693 // that if so. Otherwise we need to generate a new genesis spec. 1694 chaindb := MakeChainDatabase(ctx, stack) 1695 if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) { 1696 cfg.Genesis = nil // fallback to db content 1697 } 1698 chaindb.Close() 1699 } 1700 if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(LegacyMinerGasPriceFlag.Name) { 1701 cfg.Miner.GasPrice = big.NewInt(1) 1702 } 1703 default: 1704 if cfg.NetworkId == 1 { 1705 SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash) 1706 } 1707 } 1708 } 1709 1710 // SetDNSDiscoveryDefaults configures DNS discovery with the given URL if 1711 // no URLs are set. 1712 func SetDNSDiscoveryDefaults(cfg *eth.Config, genesis common.Hash) { 1713 if cfg.EthDiscoveryURLs != nil { 1714 return // already set through flags/config 1715 } 1716 protocol := "all" 1717 if cfg.SyncMode == downloader.LightSync { 1718 protocol = "les" 1719 } 1720 if url := params.KnownDNSNetwork(genesis, protocol); url != "" { 1721 cfg.EthDiscoveryURLs = []string{url} 1722 } 1723 if cfg.SyncMode == downloader.SnapSync { 1724 if url := params.KnownDNSNetwork(genesis, "snap"); url != "" { 1725 cfg.SnapDiscoveryURLs = []string{url} 1726 } 1727 } 1728 } 1729 1730 // RegisterEthService adds an Ethereum client to the stack. 1731 func RegisterEthService(stack *node.Node, cfg *eth.Config) ethapi.Backend { 1732 if cfg.SyncMode == downloader.LightSync { 1733 backend, err := les.New(stack, cfg) 1734 if err != nil { 1735 Fatalf("Failed to register the Ethereum service: %v", err) 1736 } 1737 stack.RegisterAPIs(tracers.APIs(backend.ApiBackend)) 1738 return backend.ApiBackend 1739 } 1740 backend, err := eth.New(stack, cfg) 1741 if err != nil { 1742 Fatalf("Failed to register the Ethereum service: %v", err) 1743 } 1744 if cfg.LightServ > 0 { 1745 _, err := les.NewLesServer(stack, backend, cfg) 1746 if err != nil { 1747 Fatalf("Failed to create the LES server: %v", err) 1748 } 1749 } 1750 stack.RegisterAPIs(tracers.APIs(backend.APIBackend)) 1751 return backend.APIBackend 1752 } 1753 1754 // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to 1755 // the given node. 1756 func RegisterEthStatsService(stack *node.Node, backend ethapi.Backend, url string) { 1757 if err := ethstats.New(stack, backend, backend.Engine(), url); err != nil { 1758 Fatalf("Failed to register the Ethereum Stats service: %v", err) 1759 } 1760 } 1761 1762 // RegisterGraphQLService is a utility function to construct a new service and register it against a node. 1763 func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, cfg node.Config) { 1764 if err := graphql.New(stack, backend, cfg.GraphQLCors, cfg.GraphQLVirtualHosts); err != nil { 1765 Fatalf("Failed to register the GraphQL service: %v", err) 1766 } 1767 } 1768 1769 func SetupMetrics(ctx *cli.Context) { 1770 if metrics.Enabled { 1771 log.Info("Enabling metrics collection") 1772 1773 var ( 1774 enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name) 1775 endpoint = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name) 1776 database = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name) 1777 username = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name) 1778 password = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name) 1779 ) 1780 1781 if enableExport { 1782 tagsMap := SplitTagsFlag(ctx.GlobalString(MetricsInfluxDBTagsFlag.Name)) 1783 1784 log.Info("Enabling metrics export to InfluxDB") 1785 1786 go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap) 1787 } 1788 1789 if ctx.GlobalIsSet(MetricsHTTPFlag.Name) { 1790 address := fmt.Sprintf("%s:%d", ctx.GlobalString(MetricsHTTPFlag.Name), ctx.GlobalInt(MetricsPortFlag.Name)) 1791 log.Info("Enabling stand-alone metrics HTTP endpoint", "address", address) 1792 exp.Setup(address) 1793 } 1794 } 1795 } 1796 1797 func SplitTagsFlag(tagsFlag string) map[string]string { 1798 tags := strings.Split(tagsFlag, ",") 1799 tagsMap := map[string]string{} 1800 1801 for _, t := range tags { 1802 if t != "" { 1803 kv := strings.Split(t, "=") 1804 1805 if len(kv) == 2 { 1806 tagsMap[kv[0]] = kv[1] 1807 } 1808 } 1809 } 1810 1811 return tagsMap 1812 } 1813 1814 // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails. 1815 func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { 1816 var ( 1817 cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 1818 handles = makeDatabaseHandles() 1819 1820 err error 1821 chainDb ethdb.Database 1822 ) 1823 if ctx.GlobalString(SyncModeFlag.Name) == "light" { 1824 name := "lightchaindata" 1825 chainDb, err = stack.OpenDatabase(name, cache, handles, "") 1826 } else { 1827 name := "chaindata" 1828 chainDb, err = stack.OpenDatabaseWithFreezer(name, cache, handles, ctx.GlobalString(AncientFlag.Name), "") 1829 } 1830 if err != nil { 1831 Fatalf("Could not open database: %v", err) 1832 } 1833 return chainDb 1834 } 1835 1836 func MakeGenesis(ctx *cli.Context) *core.Genesis { 1837 var genesis *core.Genesis 1838 switch { 1839 case ctx.GlobalBool(LegacyTestnetFlag.Name) || ctx.GlobalBool(RopstenFlag.Name): 1840 genesis = core.DefaultRopstenGenesisBlock() 1841 case ctx.GlobalBool(RinkebyFlag.Name): 1842 genesis = core.DefaultRinkebyGenesisBlock() 1843 case ctx.GlobalBool(GoerliFlag.Name): 1844 genesis = core.DefaultGoerliGenesisBlock() 1845 case ctx.GlobalBool(YoloV3Flag.Name): 1846 genesis = core.DefaultYoloV3GenesisBlock() 1847 case ctx.GlobalBool(DeveloperFlag.Name): 1848 Fatalf("Developer chains are ephemeral") 1849 } 1850 return genesis 1851 } 1852 1853 // MakeChain creates a chain manager from set command line flags. 1854 func MakeChain(ctx *cli.Context, stack *node.Node, readOnly bool) (chain *core.BlockChain, chainDb ethdb.Database) { 1855 var err error 1856 chainDb = MakeChainDatabase(ctx, stack) 1857 config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx)) 1858 if err != nil { 1859 Fatalf("%v", err) 1860 } 1861 var engine consensus.Engine 1862 if config.Clique != nil { 1863 engine = clique.New(config.Clique, chainDb) 1864 } else { 1865 engine = ethash.NewFaker() 1866 if !ctx.GlobalBool(FakePoWFlag.Name) { 1867 engine = ethash.New(ethash.Config{ 1868 CacheDir: stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir), 1869 CachesInMem: eth.DefaultConfig.Ethash.CachesInMem, 1870 CachesOnDisk: eth.DefaultConfig.Ethash.CachesOnDisk, 1871 CachesLockMmap: eth.DefaultConfig.Ethash.CachesLockMmap, 1872 DatasetDir: stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir), 1873 DatasetsInMem: eth.DefaultConfig.Ethash.DatasetsInMem, 1874 DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk, 1875 DatasetsLockMmap: eth.DefaultConfig.Ethash.DatasetsLockMmap, 1876 }, nil, false) 1877 } 1878 } 1879 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 1880 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 1881 } 1882 cache := &core.CacheConfig{ 1883 TrieCleanLimit: eth.DefaultConfig.TrieCleanCache, 1884 TrieCleanNoPrefetch: ctx.GlobalBool(CacheNoPrefetchFlag.Name), 1885 TrieDirtyLimit: eth.DefaultConfig.TrieDirtyCache, 1886 TrieDirtyDisabled: ctx.GlobalString(GCModeFlag.Name) == "archive", 1887 TrieTimeLimit: eth.DefaultConfig.TrieTimeout, 1888 SnapshotLimit: eth.DefaultConfig.SnapshotCache, 1889 Preimages: ctx.GlobalBool(CachePreimagesFlag.Name), 1890 } 1891 if cache.TrieDirtyDisabled && !cache.Preimages { 1892 cache.Preimages = true 1893 log.Info("Enabling recording of key preimages since archive mode is used") 1894 } 1895 if !ctx.GlobalIsSet(SnapshotFlag.Name) { 1896 cache.SnapshotLimit = 0 // Disabled 1897 } 1898 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) { 1899 cache.TrieCleanLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100 1900 } 1901 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 1902 cache.TrieDirtyLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 1903 } 1904 vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)} 1905 var limit *uint64 1906 if ctx.GlobalIsSet(TxLookupLimitFlag.Name) && !readOnly { 1907 l := ctx.GlobalUint64(TxLookupLimitFlag.Name) 1908 limit = &l 1909 } 1910 chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil, limit) 1911 if err != nil { 1912 Fatalf("Can't create BlockChain: %v", err) 1913 } 1914 return chain, chainDb 1915 } 1916 1917 // MakeConsolePreloads retrieves the absolute paths for the console JavaScript 1918 // scripts to preload before starting. 1919 func MakeConsolePreloads(ctx *cli.Context) []string { 1920 // Skip preloading if there's nothing to preload 1921 if ctx.GlobalString(PreloadJSFlag.Name) == "" { 1922 return nil 1923 } 1924 // Otherwise resolve absolute paths and return them 1925 var preloads []string 1926 1927 for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") { 1928 preloads = append(preloads, strings.TrimSpace(file)) 1929 } 1930 return preloads 1931 } 1932 1933 // MigrateFlags sets the global flag from a local flag when it's set. 1934 // This is a temporary function used for migrating old command/flags to the 1935 // new format. 1936 // 1937 // e.g. geth account new --keystore /tmp/mykeystore --lightkdf 1938 // 1939 // is equivalent after calling this method with: 1940 // 1941 // geth --keystore /tmp/mykeystore --lightkdf account new 1942 // 1943 // This allows the use of the existing configuration functionality. 1944 // When all flags are migrated this function can be removed and the existing 1945 // configuration functionality must be changed that is uses local flags 1946 func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error { 1947 return func(ctx *cli.Context) error { 1948 for _, name := range ctx.FlagNames() { 1949 if ctx.IsSet(name) { 1950 ctx.GlobalSet(name, ctx.String(name)) 1951 } 1952 } 1953 return action(ctx) 1954 } 1955 }