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