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