github.com/ethereum/go-ethereum@v1.16.1/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 "slices" 24 "sort" 25 "strconv" 26 "time" 27 28 "github.com/ethereum/go-ethereum/accounts" 29 "github.com/ethereum/go-ethereum/cmd/utils" 30 "github.com/ethereum/go-ethereum/common" 31 "github.com/ethereum/go-ethereum/console/prompt" 32 "github.com/ethereum/go-ethereum/eth/downloader" 33 "github.com/ethereum/go-ethereum/ethclient" 34 "github.com/ethereum/go-ethereum/internal/debug" 35 "github.com/ethereum/go-ethereum/internal/flags" 36 "github.com/ethereum/go-ethereum/log" 37 "github.com/ethereum/go-ethereum/node" 38 "go.uber.org/automaxprocs/maxprocs" 39 40 // Force-load the tracer engines to trigger registration 41 _ "github.com/ethereum/go-ethereum/eth/tracers/js" 42 _ "github.com/ethereum/go-ethereum/eth/tracers/live" 43 _ "github.com/ethereum/go-ethereum/eth/tracers/native" 44 45 "github.com/urfave/cli/v2" 46 ) 47 48 const ( 49 clientIdentifier = "geth" // Client identifier to advertise over the network 50 ) 51 52 var ( 53 // flags that configure the node 54 nodeFlags = slices.Concat([]cli.Flag{ 55 utils.IdentityFlag, 56 utils.UnlockedAccountFlag, 57 utils.PasswordFileFlag, 58 utils.BootnodesFlag, 59 utils.MinFreeDiskSpaceFlag, 60 utils.KeyStoreDirFlag, 61 utils.ExternalSignerFlag, 62 utils.NoUSBFlag, // deprecated 63 utils.USBFlag, 64 utils.SmartCardDaemonPathFlag, 65 utils.OverrideOsaka, 66 utils.OverrideVerkle, 67 utils.EnablePersonal, // deprecated 68 utils.TxPoolLocalsFlag, 69 utils.TxPoolNoLocalsFlag, 70 utils.TxPoolJournalFlag, 71 utils.TxPoolRejournalFlag, 72 utils.TxPoolPriceLimitFlag, 73 utils.TxPoolPriceBumpFlag, 74 utils.TxPoolAccountSlotsFlag, 75 utils.TxPoolGlobalSlotsFlag, 76 utils.TxPoolAccountQueueFlag, 77 utils.TxPoolGlobalQueueFlag, 78 utils.TxPoolLifetimeFlag, 79 utils.BlobPoolDataDirFlag, 80 utils.BlobPoolDataCapFlag, 81 utils.BlobPoolPriceBumpFlag, 82 utils.SyncModeFlag, 83 utils.SyncTargetFlag, 84 utils.ExitWhenSyncedFlag, 85 utils.GCModeFlag, 86 utils.SnapshotFlag, 87 utils.TxLookupLimitFlag, // deprecated 88 utils.TransactionHistoryFlag, 89 utils.ChainHistoryFlag, 90 utils.LogHistoryFlag, 91 utils.LogNoHistoryFlag, 92 utils.LogExportCheckpointsFlag, 93 utils.StateHistoryFlag, 94 utils.LightKDFFlag, 95 utils.EthRequiredBlocksFlag, 96 utils.LegacyWhitelistFlag, // deprecated 97 utils.CacheFlag, 98 utils.CacheDatabaseFlag, 99 utils.CacheTrieFlag, 100 utils.CacheTrieJournalFlag, // deprecated 101 utils.CacheTrieRejournalFlag, // deprecated 102 utils.CacheGCFlag, 103 utils.CacheSnapshotFlag, 104 utils.CacheNoPrefetchFlag, 105 utils.CachePreimagesFlag, 106 utils.CacheLogSizeFlag, 107 utils.FDLimitFlag, 108 utils.CryptoKZGFlag, 109 utils.ListenPortFlag, 110 utils.DiscoveryPortFlag, 111 utils.MaxPeersFlag, 112 utils.MaxPendingPeersFlag, 113 utils.MiningEnabledFlag, // deprecated 114 utils.MinerGasLimitFlag, 115 utils.MinerGasPriceFlag, 116 utils.MinerEtherbaseFlag, // deprecated 117 utils.MinerExtraDataFlag, 118 utils.MinerRecommitIntervalFlag, 119 utils.MinerPendingFeeRecipientFlag, 120 utils.MinerNewPayloadTimeoutFlag, // deprecated 121 utils.NATFlag, 122 utils.NoDiscoverFlag, 123 utils.DiscoveryV4Flag, 124 utils.DiscoveryV5Flag, 125 utils.LegacyDiscoveryV5Flag, // deprecated 126 utils.NetrestrictFlag, 127 utils.NodeKeyFileFlag, 128 utils.NodeKeyHexFlag, 129 utils.DNSDiscoveryFlag, 130 utils.DeveloperFlag, 131 utils.DeveloperGasLimitFlag, 132 utils.DeveloperPeriodFlag, 133 utils.VMEnableDebugFlag, 134 utils.VMTraceFlag, 135 utils.VMTraceJsonConfigFlag, 136 utils.NetworkIdFlag, 137 utils.EthStatsURLFlag, 138 utils.GpoBlocksFlag, 139 utils.GpoPercentileFlag, 140 utils.GpoMaxGasPriceFlag, 141 utils.GpoIgnoreGasPriceFlag, 142 configFileFlag, 143 utils.LogDebugFlag, 144 utils.LogBacktraceAtFlag, 145 utils.BeaconApiFlag, 146 utils.BeaconApiHeaderFlag, 147 utils.BeaconThresholdFlag, 148 utils.BeaconNoFilterFlag, 149 utils.BeaconConfigFlag, 150 utils.BeaconGenesisRootFlag, 151 utils.BeaconGenesisTimeFlag, 152 utils.BeaconCheckpointFlag, 153 utils.BeaconCheckpointFileFlag, 154 }, utils.NetworkFlags, utils.DatabaseFlags) 155 156 rpcFlags = []cli.Flag{ 157 utils.HTTPEnabledFlag, 158 utils.HTTPListenAddrFlag, 159 utils.HTTPPortFlag, 160 utils.HTTPCORSDomainFlag, 161 utils.AuthListenFlag, 162 utils.AuthPortFlag, 163 utils.AuthVirtualHostsFlag, 164 utils.JWTSecretFlag, 165 utils.HTTPVirtualHostsFlag, 166 utils.GraphQLEnabledFlag, 167 utils.GraphQLCORSDomainFlag, 168 utils.GraphQLVirtualHostsFlag, 169 utils.HTTPApiFlag, 170 utils.HTTPPathPrefixFlag, 171 utils.WSEnabledFlag, 172 utils.WSListenAddrFlag, 173 utils.WSPortFlag, 174 utils.WSApiFlag, 175 utils.WSAllowedOriginsFlag, 176 utils.WSPathPrefixFlag, 177 utils.IPCDisabledFlag, 178 utils.IPCPathFlag, 179 utils.InsecureUnlockAllowedFlag, 180 utils.RPCGlobalGasCapFlag, 181 utils.RPCGlobalEVMTimeoutFlag, 182 utils.RPCGlobalTxFeeCapFlag, 183 utils.AllowUnprotectedTxs, 184 utils.BatchRequestLimit, 185 utils.BatchResponseMaxSize, 186 } 187 188 metricsFlags = []cli.Flag{ 189 utils.MetricsEnabledFlag, 190 utils.MetricsEnabledExpensiveFlag, 191 utils.MetricsHTTPFlag, 192 utils.MetricsPortFlag, 193 utils.MetricsEnableInfluxDBFlag, 194 utils.MetricsInfluxDBEndpointFlag, 195 utils.MetricsInfluxDBDatabaseFlag, 196 utils.MetricsInfluxDBUsernameFlag, 197 utils.MetricsInfluxDBPasswordFlag, 198 utils.MetricsInfluxDBTagsFlag, 199 utils.MetricsEnableInfluxDBV2Flag, 200 utils.MetricsInfluxDBTokenFlag, 201 utils.MetricsInfluxDBBucketFlag, 202 utils.MetricsInfluxDBOrganizationFlag, 203 } 204 ) 205 206 var app = flags.NewApp("the go-ethereum command line interface") 207 208 func init() { 209 // Initialize the CLI app and start Geth 210 app.Action = geth 211 app.Commands = []*cli.Command{ 212 // See chaincmd.go: 213 initCommand, 214 importCommand, 215 exportCommand, 216 importHistoryCommand, 217 exportHistoryCommand, 218 importPreimagesCommand, 219 removedbCommand, 220 dumpCommand, 221 dumpGenesisCommand, 222 pruneHistoryCommand, 223 downloadEraCommand, 224 // See accountcmd.go: 225 accountCommand, 226 walletCommand, 227 // See consolecmd.go: 228 consoleCommand, 229 attachCommand, 230 javascriptCommand, 231 // See misccmd.go: 232 versionCommand, 233 versionCheckCommand, 234 licenseCommand, 235 // See config.go 236 dumpConfigCommand, 237 // see dbcmd.go 238 dbCommand, 239 // See cmd/utils/flags_legacy.go 240 utils.ShowDeprecated, 241 // See snapshot.go 242 snapshotCommand, 243 // See verkle.go 244 verkleCommand, 245 } 246 if logTestCommand != nil { 247 app.Commands = append(app.Commands, logTestCommand) 248 } 249 sort.Sort(cli.CommandsByName(app.Commands)) 250 251 app.Flags = slices.Concat( 252 nodeFlags, 253 rpcFlags, 254 consoleFlags, 255 debug.Flags, 256 metricsFlags, 257 ) 258 flags.AutoEnvVars(app.Flags, "GETH") 259 260 app.Before = func(ctx *cli.Context) error { 261 maxprocs.Set() // Automatically set GOMAXPROCS to match Linux container CPU quota. 262 flags.MigrateGlobalFlags(ctx) 263 if err := debug.Setup(ctx); err != nil { 264 return err 265 } 266 flags.CheckEnvVars(ctx, app.Flags, "GETH") 267 return nil 268 } 269 app.After = func(ctx *cli.Context) error { 270 debug.Exit() 271 prompt.Stdin.Close() // Resets terminal mode. 272 return nil 273 } 274 } 275 276 func main() { 277 if err := app.Run(os.Args); err != nil { 278 fmt.Fprintln(os.Stderr, err) 279 os.Exit(1) 280 } 281 } 282 283 // prepare manipulates memory cache allowance and setups metric system. 284 // This function should be called before launching devp2p stack. 285 func prepare(ctx *cli.Context) { 286 // If we're running a known preset, log it for convenience. 287 switch { 288 case ctx.IsSet(utils.SepoliaFlag.Name): 289 log.Info("Starting Geth on Sepolia testnet...") 290 291 case ctx.IsSet(utils.HoleskyFlag.Name): 292 log.Info("Starting Geth on Holesky testnet...") 293 294 case ctx.IsSet(utils.HoodiFlag.Name): 295 log.Info("Starting Geth on Hoodi testnet...") 296 297 case !ctx.IsSet(utils.NetworkIdFlag.Name): 298 log.Info("Starting Geth on Ethereum mainnet...") 299 } 300 // If we're a full node on mainnet without --cache specified, bump default cache allowance 301 if !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) { 302 // Make sure we're not on any supported preconfigured testnet either 303 if !ctx.IsSet(utils.HoleskyFlag.Name) && 304 !ctx.IsSet(utils.SepoliaFlag.Name) && 305 !ctx.IsSet(utils.HoodiFlag.Name) && 306 !ctx.IsSet(utils.DeveloperFlag.Name) { 307 // Nope, we're really on mainnet. Bump that cache up! 308 log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096) 309 ctx.Set(utils.CacheFlag.Name, strconv.Itoa(4096)) 310 } 311 } 312 } 313 314 // geth is the main entry point into the system if no special subcommand is run. 315 // It creates a default node based on the command line arguments and runs it in 316 // blocking mode, waiting for it to be shut down. 317 func geth(ctx *cli.Context) error { 318 if args := ctx.Args().Slice(); len(args) > 0 { 319 return fmt.Errorf("invalid command: %q", args[0]) 320 } 321 322 prepare(ctx) 323 stack := makeFullNode(ctx) 324 defer stack.Close() 325 326 startNode(ctx, stack, false) 327 stack.Wait() 328 return nil 329 } 330 331 // startNode boots up the system node and all registered protocols, after which 332 // it starts the RPC/IPC interfaces and the miner. 333 func startNode(ctx *cli.Context, stack *node.Node, isConsole bool) { 334 // Start up the node itself 335 utils.StartNode(ctx, stack, isConsole) 336 337 if ctx.IsSet(utils.UnlockedAccountFlag.Name) { 338 log.Warn(`The "unlock" flag has been deprecated and has no effect`) 339 } 340 341 // Register wallet event handlers to open and auto-derive wallets 342 events := make(chan accounts.WalletEvent, 16) 343 stack.AccountManager().Subscribe(events) 344 345 // Create a client to interact with local geth node. 346 rpcClient := stack.Attach() 347 ethClient := ethclient.NewClient(rpcClient) 348 349 go func() { 350 // Open any wallets already attached 351 for _, wallet := range stack.AccountManager().Wallets() { 352 if err := wallet.Open(""); err != nil { 353 log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err) 354 } 355 } 356 // Listen for wallet event till termination 357 for event := range events { 358 switch event.Kind { 359 case accounts.WalletArrived: 360 if err := event.Wallet.Open(""); err != nil { 361 log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err) 362 } 363 case accounts.WalletOpened: 364 status, _ := event.Wallet.Status() 365 log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status) 366 367 var derivationPaths []accounts.DerivationPath 368 if event.Wallet.URL().Scheme == "ledger" { 369 derivationPaths = append(derivationPaths, accounts.LegacyLedgerBaseDerivationPath) 370 } 371 derivationPaths = append(derivationPaths, accounts.DefaultBaseDerivationPath) 372 373 event.Wallet.SelfDerive(derivationPaths, ethClient) 374 375 case accounts.WalletDropped: 376 log.Info("Old wallet dropped", "url", event.Wallet.URL()) 377 event.Wallet.Close() 378 } 379 } 380 }() 381 382 // Spawn a standalone goroutine for status synchronization monitoring, 383 // close the node when synchronization is complete if user required. 384 if ctx.Bool(utils.ExitWhenSyncedFlag.Name) { 385 go func() { 386 sub := stack.EventMux().Subscribe(downloader.DoneEvent{}) 387 defer sub.Unsubscribe() 388 for { 389 event := <-sub.Chan() 390 if event == nil { 391 continue 392 } 393 done, ok := event.Data.(downloader.DoneEvent) 394 if !ok { 395 continue 396 } 397 if timestamp := time.Unix(int64(done.Latest.Time), 0); time.Since(timestamp) < 10*time.Minute { 398 log.Info("Synchronisation completed", "latestnum", done.Latest.Number, "latesthash", done.Latest.Hash(), 399 "age", common.PrettyAge(timestamp)) 400 stack.Close() 401 } 402 } 403 }() 404 } 405 }