github.com/luckypickle/go-ethereum-vet@v1.14.2/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 "runtime" 25 godebug "runtime/debug" 26 "sort" 27 "strconv" 28 "strings" 29 "time" 30 31 "github.com/elastic/gosigar" 32 "github.com/luckypickle/go-ethereum-vet/accounts" 33 "github.com/luckypickle/go-ethereum-vet/accounts/keystore" 34 "github.com/luckypickle/go-ethereum-vet/cmd/utils" 35 "github.com/luckypickle/go-ethereum-vet/console" 36 _ "github.com/luckypickle/go-ethereum-vet/crypto/blake2b" 37 "github.com/luckypickle/go-ethereum-vet/eth" 38 "github.com/luckypickle/go-ethereum-vet/ethclient" 39 "github.com/luckypickle/go-ethereum-vet/internal/debug" 40 "github.com/luckypickle/go-ethereum-vet/log" 41 "github.com/luckypickle/go-ethereum-vet/metrics" 42 "github.com/luckypickle/go-ethereum-vet/node" 43 "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.NoUSBFlag, 66 utils.EthashCacheDirFlag, 67 utils.EthashCachesInMemoryFlag, 68 utils.EthashCachesOnDiskFlag, 69 utils.EthashDatasetDirFlag, 70 utils.EthashDatasetsInMemoryFlag, 71 utils.EthashDatasetsOnDiskFlag, 72 utils.TxPoolLocalsFlag, 73 utils.TxPoolNoLocalsFlag, 74 utils.TxPoolJournalFlag, 75 utils.TxPoolRejournalFlag, 76 utils.TxPoolPriceLimitFlag, 77 utils.TxPoolPriceBumpFlag, 78 utils.TxPoolAccountSlotsFlag, 79 utils.TxPoolGlobalSlotsFlag, 80 utils.TxPoolAccountQueueFlag, 81 utils.TxPoolGlobalQueueFlag, 82 utils.TxPoolLifetimeFlag, 83 utils.SyncModeFlag, 84 utils.GCModeFlag, 85 utils.LightServFlag, 86 utils.LightPeersFlag, 87 utils.LightKDFFlag, 88 utils.CacheFlag, 89 utils.CacheDatabaseFlag, 90 utils.CacheGCFlag, 91 utils.TrieCacheGenFlag, 92 utils.ListenPortFlag, 93 utils.MaxPeersFlag, 94 utils.MaxPendingPeersFlag, 95 utils.MiningEnabledFlag, 96 utils.MinerThreadsFlag, 97 utils.MinerLegacyThreadsFlag, 98 utils.MinerNotifyFlag, 99 utils.MinerGasTargetFlag, 100 utils.MinerLegacyGasTargetFlag, 101 utils.MinerGasPriceFlag, 102 utils.MinerLegacyGasPriceFlag, 103 utils.MinerEtherbaseFlag, 104 utils.MinerLegacyEtherbaseFlag, 105 utils.MinerExtraDataFlag, 106 utils.MinerLegacyExtraDataFlag, 107 utils.MinerRecommitIntervalFlag, 108 utils.NATFlag, 109 utils.NoDiscoverFlag, 110 utils.DiscoveryV5Flag, 111 utils.NetrestrictFlag, 112 utils.NodeKeyFileFlag, 113 utils.NodeKeyHexFlag, 114 utils.DeveloperFlag, 115 utils.DeveloperPeriodFlag, 116 utils.TestnetFlag, 117 utils.RinkebyFlag, 118 utils.VMEnableDebugFlag, 119 utils.NetworkIdFlag, 120 utils.RPCCORSDomainFlag, 121 utils.RPCVirtualHostsFlag, 122 utils.EthStatsURLFlag, 123 utils.MetricsEnabledFlag, 124 utils.FakePoWFlag, 125 utils.NoCompactionFlag, 126 utils.GpoBlocksFlag, 127 utils.GpoPercentileFlag, 128 configFileFlag, 129 } 130 131 rpcFlags = []cli.Flag{ 132 utils.RPCEnabledFlag, 133 utils.RPCListenAddrFlag, 134 utils.RPCPortFlag, 135 utils.RPCApiFlag, 136 utils.WSEnabledFlag, 137 utils.WSListenAddrFlag, 138 utils.WSPortFlag, 139 utils.WSApiFlag, 140 utils.WSAllowedOriginsFlag, 141 utils.IPCDisabledFlag, 142 utils.IPCPathFlag, 143 } 144 145 whisperFlags = []cli.Flag{ 146 utils.WhisperEnabledFlag, 147 utils.WhisperMaxMessageSizeFlag, 148 utils.WhisperMinPOWFlag, 149 } 150 151 metricsFlags = []cli.Flag{ 152 utils.MetricsEnableInfluxDBFlag, 153 utils.MetricsInfluxDBEndpointFlag, 154 utils.MetricsInfluxDBDatabaseFlag, 155 utils.MetricsInfluxDBUsernameFlag, 156 utils.MetricsInfluxDBPasswordFlag, 157 utils.MetricsInfluxDBHostTagFlag, 158 } 159 ) 160 161 func init() { 162 // Initialize the CLI app and start Geth 163 app.Action = geth 164 app.HideVersion = true // we have a command to print the version 165 app.Copyright = "Copyright 2013-2018 The go-ethereum Authors" 166 app.Commands = []cli.Command{ 167 // See chaincmd.go: 168 initCommand, 169 importCommand, 170 exportCommand, 171 importPreimagesCommand, 172 exportPreimagesCommand, 173 copydbCommand, 174 removedbCommand, 175 dumpCommand, 176 // See monitorcmd.go: 177 monitorCommand, 178 // See accountcmd.go: 179 accountCommand, 180 walletCommand, 181 // See consolecmd.go: 182 consoleCommand, 183 attachCommand, 184 javascriptCommand, 185 // See misccmd.go: 186 makecacheCommand, 187 makedagCommand, 188 versionCommand, 189 bugCommand, 190 licenseCommand, 191 // See config.go 192 dumpConfigCommand, 193 } 194 sort.Sort(cli.CommandsByName(app.Commands)) 195 196 app.Flags = append(app.Flags, nodeFlags...) 197 app.Flags = append(app.Flags, rpcFlags...) 198 app.Flags = append(app.Flags, consoleFlags...) 199 app.Flags = append(app.Flags, debug.Flags...) 200 app.Flags = append(app.Flags, whisperFlags...) 201 app.Flags = append(app.Flags, metricsFlags...) 202 203 app.Before = func(ctx *cli.Context) error { 204 runtime.GOMAXPROCS(runtime.NumCPU()) 205 206 if err := debug.Setup(ctx, ""); err != nil { 207 return err 208 } 209 // Cap the cache allowance and tune the garbage collector 210 var mem gosigar.Mem 211 if err := mem.Get(); err == nil { 212 allowance := int(mem.Total / 1024 / 1024 / 3) 213 if cache := ctx.GlobalInt(utils.CacheFlag.Name); cache > allowance { 214 log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance) 215 ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(allowance)) 216 } 217 } 218 // Ensure Go's GC ignores the database cache for trigger percentage 219 cache := ctx.GlobalInt(utils.CacheFlag.Name) 220 gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024))) 221 222 log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc)) 223 godebug.SetGCPercent(int(gogc)) 224 225 // Start metrics export if enabled 226 utils.SetupMetrics(ctx) 227 228 // Start system runtime metrics collection 229 go metrics.CollectProcessMetrics(3 * time.Second) 230 231 utils.SetupNetwork(ctx) 232 return nil 233 } 234 235 app.After = func(ctx *cli.Context) error { 236 debug.Exit() 237 console.Stdin.Close() // Resets terminal mode. 238 return nil 239 } 240 } 241 242 func main() { 243 if err := app.Run(os.Args); err != nil { 244 fmt.Fprintln(os.Stderr, err) 245 os.Exit(1) 246 } 247 } 248 249 // geth is the main entry point into the system if no special subcommand is ran. 250 // It creates a default node based on the command line arguments and runs it in 251 // blocking mode, waiting for it to be shut down. 252 func geth(ctx *cli.Context) error { 253 if args := ctx.Args(); len(args) > 0 { 254 return fmt.Errorf("invalid command: %q", args[0]) 255 } 256 node := makeFullNode(ctx) 257 startNode(ctx, node) 258 node.Wait() 259 return nil 260 } 261 262 // startNode boots up the system node and all registered protocols, after which 263 // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the 264 // miner. 265 func startNode(ctx *cli.Context, stack *node.Node) { 266 debug.Memsize.Add("node", stack) 267 268 // Start up the node itself 269 utils.StartNode(stack) 270 271 // Unlock any account specifically requested 272 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 273 274 passwords := utils.MakePasswordList(ctx) 275 unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",") 276 for i, account := range unlocks { 277 if trimmed := strings.TrimSpace(account); trimmed != "" { 278 unlockAccount(ctx, ks, trimmed, i, passwords) 279 } 280 } 281 // Register wallet event handlers to open and auto-derive wallets 282 events := make(chan accounts.WalletEvent, 16) 283 stack.AccountManager().Subscribe(events) 284 285 go func() { 286 // Create a chain state reader for self-derivation 287 rpcClient, err := stack.Attach() 288 if err != nil { 289 utils.Fatalf("Failed to attach to self: %v", err) 290 } 291 stateReader := ethclient.NewClient(rpcClient) 292 293 // Open any wallets already attached 294 for _, wallet := range stack.AccountManager().Wallets() { 295 if err := wallet.Open(""); err != nil { 296 log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err) 297 } 298 } 299 // Listen for wallet event till termination 300 for event := range events { 301 switch event.Kind { 302 case accounts.WalletArrived: 303 if err := event.Wallet.Open(""); err != nil { 304 log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err) 305 } 306 case accounts.WalletOpened: 307 status, _ := event.Wallet.Status() 308 log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status) 309 310 derivationPath := accounts.DefaultBaseDerivationPath 311 if event.Wallet.URL().Scheme == "ledger" { 312 derivationPath = accounts.DefaultLedgerBaseDerivationPath 313 } 314 event.Wallet.SelfDerive(derivationPath, stateReader) 315 316 case accounts.WalletDropped: 317 log.Info("Old wallet dropped", "url", event.Wallet.URL()) 318 event.Wallet.Close() 319 } 320 } 321 }() 322 // Start auxiliary services if enabled 323 if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) { 324 // Mining only makes sense if a full Ethereum node is running 325 if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" { 326 utils.Fatalf("Light clients do not support mining") 327 } 328 var ethereum *eth.Ethereum 329 if err := stack.Service(ðereum); err != nil { 330 utils.Fatalf("Ethereum service not running: %v", err) 331 } 332 // Use a reduced number of threads if requested 333 threads := ctx.GlobalInt(utils.MinerLegacyThreadsFlag.Name) 334 if ctx.GlobalIsSet(utils.MinerThreadsFlag.Name) { 335 threads = ctx.GlobalInt(utils.MinerThreadsFlag.Name) 336 } 337 if threads > 0 { 338 type threaded interface { 339 SetThreads(threads int) 340 } 341 if th, ok := ethereum.Engine().(threaded); ok { 342 th.SetThreads(threads) 343 } 344 } 345 // Set the gas price to the limits from the CLI and start mining 346 gasprice := utils.GlobalBig(ctx, utils.MinerLegacyGasPriceFlag.Name) 347 if ctx.IsSet(utils.MinerGasPriceFlag.Name) { 348 gasprice = utils.GlobalBig(ctx, utils.MinerGasPriceFlag.Name) 349 } 350 ethereum.TxPool().SetGasPrice(gasprice) 351 if err := ethereum.StartMining(true); err != nil { 352 utils.Fatalf("Failed to start mining: %v", err) 353 } 354 } 355 }