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