github.com/nitinawathare/ethereumassignment3@v0.0.0-20211021213010-f07344c2b868/go-ethereum/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 "math" 23 "os" 24 godebug "runtime/debug" 25 "sort" 26 "strconv" 27 "strings" 28 "time" 29 30 "github.com/elastic/gosigar" 31 "github.com/ethereum/go-ethereum/accounts" 32 "github.com/ethereum/go-ethereum/accounts/keystore" 33 "github.com/ethereum/go-ethereum/cmd/utils" 34 "github.com/ethereum/go-ethereum/common" 35 "github.com/ethereum/go-ethereum/console" 36 "github.com/ethereum/go-ethereum/eth" 37 "github.com/ethereum/go-ethereum/eth/downloader" 38 "github.com/ethereum/go-ethereum/ethclient" 39 "github.com/ethereum/go-ethereum/internal/debug" 40 "github.com/ethereum/go-ethereum/log" 41 "github.com/ethereum/go-ethereum/metrics" 42 "github.com/ethereum/go-ethereum/node" 43 cli "gopkg.in/urfave/cli.v1" 44 ) 45 46 const ( 47 clientIdentifier = "geth" // Client identifier to advertise over the network 48 ) 49 50 var ( 51 // Git SHA1 commit hash of the release (set via linker flags) 52 gitCommit = "" 53 // The app that holds all commands and flags. 54 app = utils.NewApp(gitCommit, "the go-ethereum command line interface") 55 // flags that configure the node 56 nodeFlags = []cli.Flag{ 57 utils.IdentityFlag, 58 utils.UnlockedAccountFlag, 59 utils.PasswordFileFlag, 60 utils.BootnodesFlag, 61 utils.BootnodesV4Flag, 62 utils.BootnodesV5Flag, 63 utils.DataDirFlag, 64 utils.KeyStoreDirFlag, 65 utils.ExternalSignerFlag, 66 utils.NoUSBFlag, 67 utils.DashboardEnabledFlag, 68 utils.DashboardAddrFlag, 69 utils.DashboardPortFlag, 70 utils.DashboardRefreshFlag, 71 utils.EthashCacheDirFlag, 72 utils.EthashCachesInMemoryFlag, 73 utils.EthashCachesOnDiskFlag, 74 utils.EthashDatasetDirFlag, 75 utils.EthashDatasetsInMemoryFlag, 76 utils.EthashDatasetsOnDiskFlag, 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.ULCModeConfigFlag, 89 utils.OnlyAnnounceModeFlag, 90 utils.ULCTrustedNodesFlag, 91 utils.ULCMinTrustedFractionFlag, 92 utils.SyncModeFlag, 93 utils.ExitWhenSyncedFlag, 94 utils.GCModeFlag, 95 utils.LightServFlag, 96 utils.LightBandwidthInFlag, 97 utils.LightBandwidthOutFlag, 98 utils.LightPeersFlag, 99 utils.LightKDFFlag, 100 utils.WhitelistFlag, 101 utils.CacheFlag, 102 utils.CacheDatabaseFlag, 103 utils.CacheTrieFlag, 104 utils.CacheGCFlag, 105 utils.CacheNoPrefetchFlag, 106 utils.ListenPortFlag, 107 utils.MaxPeersFlag, 108 utils.MaxPendingPeersFlag, 109 utils.MiningEnabledFlag, 110 utils.MinerThreadsFlag, 111 utils.MinerLegacyThreadsFlag, 112 utils.MinerNotifyFlag, 113 utils.MinerGasTargetFlag, 114 utils.MinerLegacyGasTargetFlag, 115 utils.MinerGasLimitFlag, 116 utils.MinerGasPriceFlag, 117 utils.MinerLegacyGasPriceFlag, 118 utils.MinerEtherbaseFlag, 119 utils.MinerLegacyEtherbaseFlag, 120 utils.MinerExtraDataFlag, 121 utils.MinerLegacyExtraDataFlag, 122 utils.MinerRecommitIntervalFlag, 123 utils.MinerNoVerfiyFlag, 124 utils.NATFlag, 125 utils.NoDiscoverFlag, 126 utils.DiscoveryV5Flag, 127 utils.NetrestrictFlag, 128 utils.NodeKeyFileFlag, 129 utils.NodeKeyHexFlag, 130 utils.DeveloperFlag, 131 utils.DeveloperPeriodFlag, 132 utils.TestnetFlag, 133 utils.RinkebyFlag, 134 utils.GoerliFlag, 135 utils.VMEnableDebugFlag, 136 utils.InterArrivalFlag, 137 utils.HashPowerFlag, 138 utils.BehaviorFlag, 139 utils.NetworkIdFlag, 140 utils.ConstantinopleOverrideFlag, 141 utils.EthStatsURLFlag, 142 utils.FakePoWFlag, 143 utils.NoCompactionFlag, 144 utils.GpoBlocksFlag, 145 utils.GpoPercentileFlag, 146 utils.EWASMInterpreterFlag, 147 utils.EVMInterpreterFlag, 148 configFileFlag, 149 } 150 151 rpcFlags = []cli.Flag{ 152 utils.RPCEnabledFlag, 153 utils.RPCListenAddrFlag, 154 utils.RPCPortFlag, 155 utils.RPCCORSDomainFlag, 156 utils.RPCVirtualHostsFlag, 157 utils.GraphQLEnabledFlag, 158 utils.GraphQLListenAddrFlag, 159 utils.GraphQLPortFlag, 160 utils.GraphQLCORSDomainFlag, 161 utils.GraphQLVirtualHostsFlag, 162 utils.RPCApiFlag, 163 utils.WSEnabledFlag, 164 utils.WSListenAddrFlag, 165 utils.WSPortFlag, 166 utils.WSApiFlag, 167 utils.WSAllowedOriginsFlag, 168 utils.IPCDisabledFlag, 169 utils.IPCPathFlag, 170 utils.InsecureUnlockAllowedFlag, 171 utils.RPCGlobalGasCap, 172 } 173 174 whisperFlags = []cli.Flag{ 175 utils.WhisperEnabledFlag, 176 utils.WhisperMaxMessageSizeFlag, 177 utils.WhisperMinPOWFlag, 178 utils.WhisperRestrictConnectionBetweenLightClientsFlag, 179 } 180 181 metricsFlags = []cli.Flag{ 182 utils.MetricsEnabledFlag, 183 utils.MetricsEnabledExpensiveFlag, 184 utils.MetricsEnableInfluxDBFlag, 185 utils.MetricsInfluxDBEndpointFlag, 186 utils.MetricsInfluxDBDatabaseFlag, 187 utils.MetricsInfluxDBUsernameFlag, 188 utils.MetricsInfluxDBPasswordFlag, 189 utils.MetricsInfluxDBTagsFlag, 190 } 191 ) 192 193 func init() { 194 // Initialize the CLI app and start Geth 195 app.Action = geth 196 app.HideVersion = true // we have a command to print the version 197 app.Copyright = "Copyright 2013-2019 The go-ethereum Authors" 198 app.Commands = []cli.Command{ 199 // See chaincmd.go: 200 initCommand, 201 importCommand, 202 exportCommand, 203 importPreimagesCommand, 204 exportPreimagesCommand, 205 copydbCommand, 206 removedbCommand, 207 dumpCommand, 208 // See accountcmd.go: 209 accountCommand, 210 walletCommand, 211 // See consolecmd.go: 212 consoleCommand, 213 attachCommand, 214 javascriptCommand, 215 // See misccmd.go: 216 makecacheCommand, 217 makedagCommand, 218 versionCommand, 219 licenseCommand, 220 // See config.go 221 dumpConfigCommand, 222 } 223 sort.Sort(cli.CommandsByName(app.Commands)) 224 225 app.Flags = append(app.Flags, nodeFlags...) 226 app.Flags = append(app.Flags, rpcFlags...) 227 app.Flags = append(app.Flags, consoleFlags...) 228 app.Flags = append(app.Flags, debug.Flags...) 229 app.Flags = append(app.Flags, whisperFlags...) 230 app.Flags = append(app.Flags, metricsFlags...) 231 232 app.Before = func(ctx *cli.Context) error { 233 logdir := "" 234 if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) { 235 logdir = (&node.Config{DataDir: utils.MakeDataDir(ctx)}).ResolvePath("logs") 236 } 237 if err := debug.Setup(ctx, logdir); err != nil { 238 return err 239 } 240 // If we're a full node on mainnet without --cache specified, bump default cache allowance 241 if ctx.GlobalString(utils.SyncModeFlag.Name) != "light" && !ctx.GlobalIsSet(utils.CacheFlag.Name) && !ctx.GlobalIsSet(utils.NetworkIdFlag.Name) { 242 // Make sure we're not on any supported preconfigured testnet either 243 if !ctx.GlobalIsSet(utils.TestnetFlag.Name) && !ctx.GlobalIsSet(utils.RinkebyFlag.Name) && !ctx.GlobalIsSet(utils.GoerliFlag.Name) { 244 // Nope, we're really on mainnet. Bump that cache up! 245 log.Info("Bumping default cache on mainnet", "provided", ctx.GlobalInt(utils.CacheFlag.Name), "updated", 4096) 246 ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(4096)) 247 } 248 } 249 // If we're running a light client on any network, drop the cache to some meaningfully low amount 250 if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" && !ctx.GlobalIsSet(utils.CacheFlag.Name) { 251 log.Info("Dropping default light client cache", "provided", ctx.GlobalInt(utils.CacheFlag.Name), "updated", 128) 252 ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(128)) 253 } 254 // Cap the cache allowance and tune the garbage collector 255 var mem gosigar.Mem 256 if err := mem.Get(); err == nil { 257 allowance := int(mem.Total / 1024 / 1024 / 3) 258 if cache := ctx.GlobalInt(utils.CacheFlag.Name); cache > allowance { 259 log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance) 260 ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(allowance)) 261 } 262 } 263 // Ensure Go's GC ignores the database cache for trigger percentage 264 cache := ctx.GlobalInt(utils.CacheFlag.Name) 265 gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024))) 266 267 log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc)) 268 godebug.SetGCPercent(int(gogc)) 269 270 // Start metrics export if enabled 271 utils.SetupMetrics(ctx) 272 273 // Start system runtime metrics collection 274 go metrics.CollectProcessMetrics(3 * time.Second) 275 276 return nil 277 } 278 279 app.After = func(ctx *cli.Context) error { 280 debug.Exit() 281 console.Stdin.Close() // Resets terminal mode. 282 return nil 283 } 284 } 285 286 func main() { 287 if err := app.Run(os.Args); err != nil { 288 fmt.Fprintln(os.Stderr, err) 289 os.Exit(1) 290 } 291 } 292 293 // geth is the main entry point into the system if no special subcommand is ran. 294 // It creates a default node based on the command line arguments and runs it in 295 // blocking mode, waiting for it to be shut down. 296 func geth(ctx *cli.Context) error { 297 if args := ctx.Args(); len(args) > 0 { 298 return fmt.Errorf("invalid command: %q", args[0]) 299 } 300 node := makeFullNode(ctx) 301 defer node.Close() 302 startNode(ctx, node) 303 node.Wait() 304 return nil 305 } 306 307 // startNode boots up the system node and all registered protocols, after which 308 // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the 309 // miner. 310 func startNode(ctx *cli.Context, stack *node.Node) { 311 debug.Memsize.Add("node", stack) 312 313 // Start up the node itself 314 utils.StartNode(stack) 315 316 // Unlock any account specifically requested 317 unlockAccounts(ctx, stack) 318 319 // Register wallet event handlers to open and auto-derive wallets 320 events := make(chan accounts.WalletEvent, 16) 321 stack.AccountManager().Subscribe(events) 322 323 go func() { 324 // Create a chain state reader for self-derivation 325 rpcClient, err := stack.Attach() 326 if err != nil { 327 utils.Fatalf("Failed to attach to self: %v", err) 328 } 329 stateReader := ethclient.NewClient(rpcClient) 330 331 // Open any wallets already attached 332 for _, wallet := range stack.AccountManager().Wallets() { 333 if err := wallet.Open(""); err != nil { 334 log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err) 335 } 336 } 337 // Listen for wallet event till termination 338 for event := range events { 339 switch event.Kind { 340 case accounts.WalletArrived: 341 if err := event.Wallet.Open(""); err != nil { 342 log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err) 343 } 344 case accounts.WalletOpened: 345 status, _ := event.Wallet.Status() 346 log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status) 347 348 derivationPath := accounts.DefaultBaseDerivationPath 349 if event.Wallet.URL().Scheme == "ledger" { 350 derivationPath = accounts.DefaultLedgerBaseDerivationPath 351 } 352 event.Wallet.SelfDerive(derivationPath, stateReader) 353 354 case accounts.WalletDropped: 355 log.Info("Old wallet dropped", "url", event.Wallet.URL()) 356 event.Wallet.Close() 357 } 358 } 359 }() 360 361 // Spawn a standalone goroutine for status synchronization monitoring, 362 // close the node when synchronization is complete if user required. 363 if ctx.GlobalBool(utils.ExitWhenSyncedFlag.Name) { 364 go func() { 365 sub := stack.EventMux().Subscribe(downloader.DoneEvent{}) 366 defer sub.Unsubscribe() 367 for { 368 event := <-sub.Chan() 369 if event == nil { 370 continue 371 } 372 done, ok := event.Data.(downloader.DoneEvent) 373 if !ok { 374 continue 375 } 376 if timestamp := time.Unix(int64(done.Latest.Time), 0); time.Since(timestamp) < 10*time.Minute { 377 log.Info("Synchronisation completed", "latestnum", done.Latest.Number, "latesthash", done.Latest.Hash(), 378 "age", common.PrettyAge(timestamp)) 379 stack.Stop() 380 } 381 382 } 383 }() 384 } 385 386 // Start auxiliary services if enabled 387 if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) { 388 // Mining only makes sense if a full Ethereum node is running 389 if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" { 390 utils.Fatalf("Light clients do not support mining") 391 } 392 var ethereum *eth.Ethereum 393 if err := stack.Service(ðereum); err != nil { 394 utils.Fatalf("Ethereum service not running: %v", err) 395 } 396 // Set the gas price to the limits from the CLI and start mining 397 gasprice := utils.GlobalBig(ctx, utils.MinerLegacyGasPriceFlag.Name) 398 if ctx.IsSet(utils.MinerGasPriceFlag.Name) { 399 gasprice = utils.GlobalBig(ctx, utils.MinerGasPriceFlag.Name) 400 } 401 ethereum.TxPool().SetGasPrice(gasprice) 402 403 threads := ctx.GlobalInt(utils.MinerLegacyThreadsFlag.Name) 404 if ctx.GlobalIsSet(utils.MinerThreadsFlag.Name) { 405 threads = ctx.GlobalInt(utils.MinerThreadsFlag.Name) 406 } 407 if err := ethereum.StartMining(threads); err != nil { 408 utils.Fatalf("Failed to start mining: %v", err) 409 } 410 } 411 } 412 413 // unlockAccounts unlocks any account specifically requested. 414 func unlockAccounts(ctx *cli.Context, stack *node.Node) { 415 var unlocks []string 416 inputs := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",") 417 for _, input := range inputs { 418 if trimmed := strings.TrimSpace(input); trimmed != "" { 419 unlocks = append(unlocks, trimmed) 420 } 421 } 422 // Short circuit if there is no account to unlock. 423 if len(unlocks) == 0 { 424 return 425 } 426 // If insecure account unlocking is not allowed if node's APIs are exposed to external. 427 // Print warning log to user and skip unlocking. 428 if !stack.Config().InsecureUnlockAllowed && stack.Config().ExtRPCEnabled() { 429 utils.Fatalf("Account unlock with HTTP access is forbidden!") 430 } 431 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 432 passwords := utils.MakePasswordList(ctx) 433 for i, account := range unlocks { 434 unlockAccount(ks, account, i, passwords) 435 } 436 }