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