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