github.com/carter-ya/go-ethereum@v0.0.0-20230628080049-d2309be3983b/cmd/geth/main.go (about) 1 // Copyright 2014 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 // geth is the official command-line client for Ethereum. 18 package main 19 20 import ( 21 "fmt" 22 "os" 23 "sort" 24 "strconv" 25 "strings" 26 "time" 27 28 "github.com/ethereum/go-ethereum/accounts" 29 "github.com/ethereum/go-ethereum/accounts/keystore" 30 "github.com/ethereum/go-ethereum/cmd/utils" 31 "github.com/ethereum/go-ethereum/common" 32 "github.com/ethereum/go-ethereum/console/prompt" 33 "github.com/ethereum/go-ethereum/eth" 34 "github.com/ethereum/go-ethereum/eth/downloader" 35 "github.com/ethereum/go-ethereum/ethclient" 36 "github.com/ethereum/go-ethereum/internal/debug" 37 "github.com/ethereum/go-ethereum/internal/ethapi" 38 "github.com/ethereum/go-ethereum/internal/flags" 39 "github.com/ethereum/go-ethereum/log" 40 "github.com/ethereum/go-ethereum/metrics" 41 "github.com/ethereum/go-ethereum/node" 42 43 // Force-load the tracer engines to trigger registration 44 _ "github.com/ethereum/go-ethereum/eth/tracers/js" 45 _ "github.com/ethereum/go-ethereum/eth/tracers/native" 46 47 "github.com/urfave/cli/v2" 48 ) 49 50 const ( 51 clientIdentifier = "geth" // Client identifier to advertise over the network 52 ) 53 54 var ( 55 // flags that configure the node 56 nodeFlags = flags.Merge([]cli.Flag{ 57 utils.IdentityFlag, 58 utils.UnlockedAccountFlag, 59 utils.PasswordFileFlag, 60 utils.BootnodesFlag, 61 utils.MinFreeDiskSpaceFlag, 62 utils.KeyStoreDirFlag, 63 utils.ExternalSignerFlag, 64 utils.NoUSBFlag, 65 utils.USBFlag, 66 utils.SmartCardDaemonPathFlag, 67 utils.OverrideTerminalTotalDifficulty, 68 utils.OverrideTerminalTotalDifficultyPassed, 69 utils.EthashCacheDirFlag, 70 utils.EthashCachesInMemoryFlag, 71 utils.EthashCachesOnDiskFlag, 72 utils.EthashCachesLockMmapFlag, 73 utils.EthashDatasetDirFlag, 74 utils.EthashDatasetsInMemoryFlag, 75 utils.EthashDatasetsOnDiskFlag, 76 utils.EthashDatasetsLockMmapFlag, 77 utils.TxPoolLocalsFlag, 78 utils.TxPoolNoLocalsFlag, 79 utils.TxPoolJournalFlag, 80 utils.TxPoolRejournalFlag, 81 utils.TxPoolPriceLimitFlag, 82 utils.TxPoolPriceBumpFlag, 83 utils.TxPoolAccountSlotsFlag, 84 utils.TxPoolGlobalSlotsFlag, 85 utils.TxPoolAccountQueueFlag, 86 utils.TxPoolGlobalQueueFlag, 87 utils.TxPoolLifetimeFlag, 88 utils.SyncModeFlag, 89 utils.ExitWhenSyncedFlag, 90 utils.GCModeFlag, 91 utils.SnapshotFlag, 92 utils.TxLookupLimitFlag, 93 utils.LightServeFlag, 94 utils.LightIngressFlag, 95 utils.LightEgressFlag, 96 utils.LightMaxPeersFlag, 97 utils.LightNoPruneFlag, 98 utils.LightKDFFlag, 99 utils.UltraLightServersFlag, 100 utils.UltraLightFractionFlag, 101 utils.UltraLightOnlyAnnounceFlag, 102 utils.LightNoSyncServeFlag, 103 utils.EthRequiredBlocksFlag, 104 utils.LegacyWhitelistFlag, 105 utils.BloomFilterSizeFlag, 106 utils.CacheFlag, 107 utils.CacheDatabaseFlag, 108 utils.CacheTrieFlag, 109 utils.CacheTrieJournalFlag, 110 utils.CacheTrieRejournalFlag, 111 utils.CacheGCFlag, 112 utils.CacheSnapshotFlag, 113 utils.CacheNoPrefetchFlag, 114 utils.CachePreimagesFlag, 115 utils.CacheLogSizeFlag, 116 utils.FDLimitFlag, 117 utils.ListenPortFlag, 118 utils.DiscoveryPortFlag, 119 utils.MaxPeersFlag, 120 utils.MaxPendingPeersFlag, 121 utils.MiningEnabledFlag, 122 utils.MinerThreadsFlag, 123 utils.MinerNotifyFlag, 124 utils.MinerGasLimitFlag, 125 utils.MinerGasPriceFlag, 126 utils.MinerEtherbaseFlag, 127 utils.MinerExtraDataFlag, 128 utils.MinerRecommitIntervalFlag, 129 utils.MinerNoVerifyFlag, 130 utils.NATFlag, 131 utils.NoDiscoverFlag, 132 utils.DiscoveryV5Flag, 133 utils.NetrestrictFlag, 134 utils.NodeKeyFileFlag, 135 utils.NodeKeyHexFlag, 136 utils.DNSDiscoveryFlag, 137 utils.DeveloperFlag, 138 utils.DeveloperPeriodFlag, 139 utils.DeveloperGasLimitFlag, 140 utils.VMEnableDebugFlag, 141 utils.NetworkIdFlag, 142 utils.EthStatsURLFlag, 143 utils.FakePoWFlag, 144 utils.NoCompactionFlag, 145 utils.GpoBlocksFlag, 146 utils.GpoPercentileFlag, 147 utils.GpoMaxGasPriceFlag, 148 utils.GpoIgnoreGasPriceFlag, 149 utils.MinerNotifyFullFlag, 150 utils.IgnoreLegacyReceiptsFlag, 151 configFileFlag, 152 }, utils.NetworkFlags, utils.DatabasePathFlags) 153 154 rpcFlags = []cli.Flag{ 155 utils.HTTPEnabledFlag, 156 utils.HTTPListenAddrFlag, 157 utils.HTTPPortFlag, 158 utils.HTTPCORSDomainFlag, 159 utils.AuthListenFlag, 160 utils.AuthPortFlag, 161 utils.AuthVirtualHostsFlag, 162 utils.JWTSecretFlag, 163 utils.HTTPVirtualHostsFlag, 164 utils.GraphQLEnabledFlag, 165 utils.GraphQLCORSDomainFlag, 166 utils.GraphQLVirtualHostsFlag, 167 utils.HTTPApiFlag, 168 utils.HTTPPathPrefixFlag, 169 utils.WSEnabledFlag, 170 utils.WSListenAddrFlag, 171 utils.WSPortFlag, 172 utils.WSApiFlag, 173 utils.WSAllowedOriginsFlag, 174 utils.WSPathPrefixFlag, 175 utils.IPCDisabledFlag, 176 utils.IPCPathFlag, 177 utils.InsecureUnlockAllowedFlag, 178 utils.RPCGlobalGasCapFlag, 179 utils.RPCGlobalEVMTimeoutFlag, 180 utils.RPCGlobalTxFeeCapFlag, 181 utils.AllowUnprotectedTxs, 182 } 183 184 metricsFlags = []cli.Flag{ 185 utils.MetricsEnabledFlag, 186 utils.MetricsEnabledExpensiveFlag, 187 utils.MetricsHTTPFlag, 188 utils.MetricsPortFlag, 189 utils.MetricsEnableInfluxDBFlag, 190 utils.MetricsInfluxDBEndpointFlag, 191 utils.MetricsInfluxDBDatabaseFlag, 192 utils.MetricsInfluxDBUsernameFlag, 193 utils.MetricsInfluxDBPasswordFlag, 194 utils.MetricsInfluxDBTagsFlag, 195 utils.MetricsEnableInfluxDBV2Flag, 196 utils.MetricsInfluxDBTokenFlag, 197 utils.MetricsInfluxDBBucketFlag, 198 utils.MetricsInfluxDBOrganizationFlag, 199 } 200 ) 201 202 var app = flags.NewApp("the go-ethereum command line interface") 203 204 func init() { 205 // Initialize the CLI app and start Geth 206 app.Action = geth 207 app.HideVersion = true // we have a command to print the version 208 app.Copyright = "Copyright 2013-2022 The go-ethereum Authors" 209 app.Commands = []*cli.Command{ 210 // See chaincmd.go: 211 initCommand, 212 importCommand, 213 exportCommand, 214 importPreimagesCommand, 215 exportPreimagesCommand, 216 removedbCommand, 217 dumpCommand, 218 dumpGenesisCommand, 219 // See accountcmd.go: 220 accountCommand, 221 walletCommand, 222 // See consolecmd.go: 223 consoleCommand, 224 attachCommand, 225 javascriptCommand, 226 // See misccmd.go: 227 makecacheCommand, 228 makedagCommand, 229 versionCommand, 230 versionCheckCommand, 231 licenseCommand, 232 // See config.go 233 dumpConfigCommand, 234 // see dbcmd.go 235 dbCommand, 236 // See cmd/utils/flags_legacy.go 237 utils.ShowDeprecated, 238 // See snapshot.go 239 snapshotCommand, 240 // See verkle.go 241 verkleCommand, 242 } 243 sort.Sort(cli.CommandsByName(app.Commands)) 244 245 app.Flags = flags.Merge( 246 nodeFlags, 247 rpcFlags, 248 consoleFlags, 249 debug.Flags, 250 metricsFlags, 251 ) 252 253 app.Before = func(ctx *cli.Context) error { 254 flags.MigrateGlobalFlags(ctx) 255 return debug.Setup(ctx) 256 } 257 app.After = func(ctx *cli.Context) error { 258 debug.Exit() 259 prompt.Stdin.Close() // Resets terminal mode. 260 return nil 261 } 262 } 263 264 func main() { 265 if err := app.Run(os.Args); err != nil { 266 fmt.Fprintln(os.Stderr, err) 267 os.Exit(1) 268 } 269 } 270 271 // prepare manipulates memory cache allowance and setups metric system. 272 // This function should be called before launching devp2p stack. 273 func prepare(ctx *cli.Context) { 274 // If we're running a known preset, log it for convenience. 275 switch { 276 case ctx.IsSet(utils.RopstenFlag.Name): 277 log.Info("Starting Geth on Ropsten testnet...") 278 279 case ctx.IsSet(utils.RinkebyFlag.Name): 280 log.Info("Starting Geth on Rinkeby testnet...") 281 282 case ctx.IsSet(utils.GoerliFlag.Name): 283 log.Info("Starting Geth on Görli testnet...") 284 285 case ctx.IsSet(utils.SepoliaFlag.Name): 286 log.Info("Starting Geth on Sepolia testnet...") 287 288 case ctx.IsSet(utils.KilnFlag.Name): 289 log.Info("Starting Geth on Kiln testnet...") 290 291 case ctx.IsSet(utils.DeveloperFlag.Name): 292 log.Info("Starting Geth in ephemeral dev mode...") 293 log.Warn(`You are running Geth in --dev mode. Please note the following: 294 295 1. This mode is only intended for fast, iterative development without assumptions on 296 security or persistence. 297 2. The database is created in memory unless specified otherwise. Therefore, shutting down 298 your computer or losing power will wipe your entire block data and chain state for 299 your dev environment. 300 3. A random, pre-allocated developer account will be available and unlocked as 301 eth.coinbase, which can be used for testing. The random dev account is temporary, 302 stored on a ramdisk, and will be lost if your machine is restarted. 303 4. Mining is enabled by default. However, the client will only seal blocks if transactions 304 are pending in the mempool. The miner's minimum accepted gas price is 1. 305 5. Networking is disabled; there is no listen-address, the maximum number of peers is set 306 to 0, and discovery is disabled. 307 `) 308 309 case !ctx.IsSet(utils.NetworkIdFlag.Name): 310 log.Info("Starting Geth on Ethereum mainnet...") 311 } 312 // If we're a full node on mainnet without --cache specified, bump default cache allowance 313 if ctx.String(utils.SyncModeFlag.Name) != "light" && !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) { 314 // Make sure we're not on any supported preconfigured testnet either 315 if !ctx.IsSet(utils.RopstenFlag.Name) && 316 !ctx.IsSet(utils.SepoliaFlag.Name) && 317 !ctx.IsSet(utils.RinkebyFlag.Name) && 318 !ctx.IsSet(utils.GoerliFlag.Name) && 319 !ctx.IsSet(utils.KilnFlag.Name) && 320 !ctx.IsSet(utils.DeveloperFlag.Name) { 321 // Nope, we're really on mainnet. Bump that cache up! 322 log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096) 323 ctx.Set(utils.CacheFlag.Name, strconv.Itoa(4096)) 324 } 325 } 326 // If we're running a light client on any network, drop the cache to some meaningfully low amount 327 if ctx.String(utils.SyncModeFlag.Name) == "light" && !ctx.IsSet(utils.CacheFlag.Name) { 328 log.Info("Dropping default light client cache", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 128) 329 ctx.Set(utils.CacheFlag.Name, strconv.Itoa(128)) 330 } 331 332 // Start metrics export if enabled 333 utils.SetupMetrics(ctx) 334 335 // Start system runtime metrics collection 336 go metrics.CollectProcessMetrics(3 * time.Second) 337 } 338 339 // geth is the main entry point into the system if no special subcommand is ran. 340 // It creates a default node based on the command line arguments and runs it in 341 // blocking mode, waiting for it to be shut down. 342 func geth(ctx *cli.Context) error { 343 if args := ctx.Args().Slice(); len(args) > 0 { 344 return fmt.Errorf("invalid command: %q", args[0]) 345 } 346 347 prepare(ctx) 348 stack, backend := makeFullNode(ctx) 349 defer stack.Close() 350 351 startNode(ctx, stack, backend, false) 352 stack.Wait() 353 return nil 354 } 355 356 // startNode boots up the system node and all registered protocols, after which 357 // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the 358 // miner. 359 func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isConsole bool) { 360 debug.Memsize.Add("node", stack) 361 362 // Start up the node itself 363 utils.StartNode(ctx, stack, isConsole) 364 365 // Unlock any account specifically requested 366 unlockAccounts(ctx, stack) 367 368 // Register wallet event handlers to open and auto-derive wallets 369 events := make(chan accounts.WalletEvent, 16) 370 stack.AccountManager().Subscribe(events) 371 372 // Create a client to interact with local geth node. 373 rpcClient, err := stack.Attach() 374 if err != nil { 375 utils.Fatalf("Failed to attach to self: %v", err) 376 } 377 ethClient := ethclient.NewClient(rpcClient) 378 379 go func() { 380 // Open any wallets already attached 381 for _, wallet := range stack.AccountManager().Wallets() { 382 if err := wallet.Open(""); err != nil { 383 log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err) 384 } 385 } 386 // Listen for wallet event till termination 387 for event := range events { 388 switch event.Kind { 389 case accounts.WalletArrived: 390 if err := event.Wallet.Open(""); err != nil { 391 log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err) 392 } 393 case accounts.WalletOpened: 394 status, _ := event.Wallet.Status() 395 log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status) 396 397 var derivationPaths []accounts.DerivationPath 398 if event.Wallet.URL().Scheme == "ledger" { 399 derivationPaths = append(derivationPaths, accounts.LegacyLedgerBaseDerivationPath) 400 } 401 derivationPaths = append(derivationPaths, accounts.DefaultBaseDerivationPath) 402 403 event.Wallet.SelfDerive(derivationPaths, ethClient) 404 405 case accounts.WalletDropped: 406 log.Info("Old wallet dropped", "url", event.Wallet.URL()) 407 event.Wallet.Close() 408 } 409 } 410 }() 411 412 // Spawn a standalone goroutine for status synchronization monitoring, 413 // close the node when synchronization is complete if user required. 414 if ctx.Bool(utils.ExitWhenSyncedFlag.Name) { 415 go func() { 416 sub := stack.EventMux().Subscribe(downloader.DoneEvent{}) 417 defer sub.Unsubscribe() 418 for { 419 event := <-sub.Chan() 420 if event == nil { 421 continue 422 } 423 done, ok := event.Data.(downloader.DoneEvent) 424 if !ok { 425 continue 426 } 427 if timestamp := time.Unix(int64(done.Latest.Time), 0); time.Since(timestamp) < 10*time.Minute { 428 log.Info("Synchronisation completed", "latestnum", done.Latest.Number, "latesthash", done.Latest.Hash(), 429 "age", common.PrettyAge(timestamp)) 430 stack.Close() 431 } 432 } 433 }() 434 } 435 436 // Start auxiliary services if enabled 437 if ctx.Bool(utils.MiningEnabledFlag.Name) || ctx.Bool(utils.DeveloperFlag.Name) { 438 // Mining only makes sense if a full Ethereum node is running 439 if ctx.String(utils.SyncModeFlag.Name) == "light" { 440 utils.Fatalf("Light clients do not support mining") 441 } 442 ethBackend, ok := backend.(*eth.EthAPIBackend) 443 if !ok { 444 utils.Fatalf("Ethereum service not running") 445 } 446 // Set the gas price to the limits from the CLI and start mining 447 gasprice := flags.GlobalBig(ctx, utils.MinerGasPriceFlag.Name) 448 ethBackend.TxPool().SetGasPrice(gasprice) 449 // start mining 450 threads := ctx.Int(utils.MinerThreadsFlag.Name) 451 if err := ethBackend.StartMining(threads); err != nil { 452 utils.Fatalf("Failed to start mining: %v", err) 453 } 454 } 455 } 456 457 // unlockAccounts unlocks any account specifically requested. 458 func unlockAccounts(ctx *cli.Context, stack *node.Node) { 459 var unlocks []string 460 inputs := strings.Split(ctx.String(utils.UnlockedAccountFlag.Name), ",") 461 for _, input := range inputs { 462 if trimmed := strings.TrimSpace(input); trimmed != "" { 463 unlocks = append(unlocks, trimmed) 464 } 465 } 466 // Short circuit if there is no account to unlock. 467 if len(unlocks) == 0 { 468 return 469 } 470 // If insecure account unlocking is not allowed if node's APIs are exposed to external. 471 // Print warning log to user and skip unlocking. 472 if !stack.Config().InsecureUnlockAllowed && stack.Config().ExtRPCEnabled() { 473 utils.Fatalf("Account unlock with HTTP access is forbidden!") 474 } 475 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 476 passwords := utils.MakePasswordList(ctx) 477 for i, account := range unlocks { 478 unlockAccount(ks, account, i, passwords) 479 } 480 }