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