github.com/clem109/go-ethereum@v1.8.3-0.20180316121352-fe6cf00f480a/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 "runtime" 24 "sort" 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" 33 "github.com/ethereum/go-ethereum/eth" 34 "github.com/ethereum/go-ethereum/ethclient" 35 "github.com/ethereum/go-ethereum/internal/debug" 36 "github.com/ethereum/go-ethereum/log" 37 "github.com/ethereum/go-ethereum/metrics" 38 "github.com/ethereum/go-ethereum/node" 39 "gopkg.in/urfave/cli.v1" 40 ) 41 42 const ( 43 clientIdentifier = "geth" // Client identifier to advertise over the network 44 ) 45 46 var ( 47 // Git SHA1 commit hash of the release (set via linker flags) 48 gitCommit = "" 49 // Ethereum address of the Geth release oracle. 50 relOracle = common.HexToAddress("0xfa7b9770ca4cb04296cac84f37736d4041251cdf") 51 // The app that holds all commands and flags. 52 app = utils.NewApp(gitCommit, "the go-ethereum command line interface") 53 // flags that configure the node 54 nodeFlags = []cli.Flag{ 55 utils.IdentityFlag, 56 utils.UnlockedAccountFlag, 57 utils.PasswordFileFlag, 58 utils.BootnodesFlag, 59 utils.BootnodesV4Flag, 60 utils.BootnodesV5Flag, 61 utils.DataDirFlag, 62 utils.KeyStoreDirFlag, 63 utils.NoUSBFlag, 64 utils.DashboardEnabledFlag, 65 utils.DashboardAddrFlag, 66 utils.DashboardPortFlag, 67 utils.DashboardRefreshFlag, 68 utils.EthashCacheDirFlag, 69 utils.EthashCachesInMemoryFlag, 70 utils.EthashCachesOnDiskFlag, 71 utils.EthashDatasetDirFlag, 72 utils.EthashDatasetsInMemoryFlag, 73 utils.EthashDatasetsOnDiskFlag, 74 utils.TxPoolNoLocalsFlag, 75 utils.TxPoolJournalFlag, 76 utils.TxPoolRejournalFlag, 77 utils.TxPoolPriceLimitFlag, 78 utils.TxPoolPriceBumpFlag, 79 utils.TxPoolAccountSlotsFlag, 80 utils.TxPoolGlobalSlotsFlag, 81 utils.TxPoolAccountQueueFlag, 82 utils.TxPoolGlobalQueueFlag, 83 utils.TxPoolLifetimeFlag, 84 utils.FastSyncFlag, 85 utils.LightModeFlag, 86 utils.SyncModeFlag, 87 utils.GCModeFlag, 88 utils.LightServFlag, 89 utils.LightPeersFlag, 90 utils.LightKDFFlag, 91 utils.CacheFlag, 92 utils.CacheDatabaseFlag, 93 utils.CacheGCFlag, 94 utils.TrieCacheGenFlag, 95 utils.ListenPortFlag, 96 utils.MaxPeersFlag, 97 utils.MaxPendingPeersFlag, 98 utils.EtherbaseFlag, 99 utils.GasPriceFlag, 100 utils.MinerThreadsFlag, 101 utils.MiningEnabledFlag, 102 utils.TargetGasLimitFlag, 103 utils.NATFlag, 104 utils.NoDiscoverFlag, 105 utils.DiscoveryV5Flag, 106 utils.NetrestrictFlag, 107 utils.NodeKeyFileFlag, 108 utils.NodeKeyHexFlag, 109 utils.DeveloperFlag, 110 utils.DeveloperPeriodFlag, 111 utils.TestnetFlag, 112 utils.RinkebyFlag, 113 utils.VMEnableDebugFlag, 114 utils.NetworkIdFlag, 115 utils.RPCCORSDomainFlag, 116 utils.RPCVirtualHostsFlag, 117 utils.EthStatsURLFlag, 118 utils.MetricsEnabledFlag, 119 utils.FakePoWFlag, 120 utils.NoCompactionFlag, 121 utils.GpoBlocksFlag, 122 utils.GpoPercentileFlag, 123 utils.ExtraDataFlag, 124 configFileFlag, 125 } 126 127 rpcFlags = []cli.Flag{ 128 utils.RPCEnabledFlag, 129 utils.RPCListenAddrFlag, 130 utils.RPCPortFlag, 131 utils.RPCApiFlag, 132 utils.WSEnabledFlag, 133 utils.WSListenAddrFlag, 134 utils.WSPortFlag, 135 utils.WSApiFlag, 136 utils.WSAllowedOriginsFlag, 137 utils.IPCDisabledFlag, 138 utils.IPCPathFlag, 139 } 140 141 whisperFlags = []cli.Flag{ 142 utils.WhisperEnabledFlag, 143 utils.WhisperMaxMessageSizeFlag, 144 utils.WhisperMinPOWFlag, 145 } 146 ) 147 148 func init() { 149 // Initialize the CLI app and start Geth 150 app.Action = geth 151 app.HideVersion = true // we have a command to print the version 152 app.Copyright = "Copyright 2013-2017 The go-ethereum Authors" 153 app.Commands = []cli.Command{ 154 // See chaincmd.go: 155 initCommand, 156 importCommand, 157 exportCommand, 158 copydbCommand, 159 removedbCommand, 160 dumpCommand, 161 // See monitorcmd.go: 162 monitorCommand, 163 // See accountcmd.go: 164 accountCommand, 165 walletCommand, 166 // See consolecmd.go: 167 consoleCommand, 168 attachCommand, 169 javascriptCommand, 170 // See misccmd.go: 171 makecacheCommand, 172 makedagCommand, 173 versionCommand, 174 bugCommand, 175 licenseCommand, 176 // See config.go 177 dumpConfigCommand, 178 } 179 sort.Sort(cli.CommandsByName(app.Commands)) 180 181 app.Flags = append(app.Flags, nodeFlags...) 182 app.Flags = append(app.Flags, rpcFlags...) 183 app.Flags = append(app.Flags, consoleFlags...) 184 app.Flags = append(app.Flags, debug.Flags...) 185 app.Flags = append(app.Flags, whisperFlags...) 186 187 app.Before = func(ctx *cli.Context) error { 188 runtime.GOMAXPROCS(runtime.NumCPU()) 189 if err := debug.Setup(ctx); err != nil { 190 return err 191 } 192 // Start system runtime metrics collection 193 go metrics.CollectProcessMetrics(3 * time.Second) 194 195 utils.SetupNetwork(ctx) 196 return nil 197 } 198 199 app.After = func(ctx *cli.Context) error { 200 debug.Exit() 201 console.Stdin.Close() // Resets terminal mode. 202 return nil 203 } 204 } 205 206 func main() { 207 if err := app.Run(os.Args); err != nil { 208 fmt.Fprintln(os.Stderr, err) 209 os.Exit(1) 210 } 211 } 212 213 // geth is the main entry point into the system if no special subcommand is ran. 214 // It creates a default node based on the command line arguments and runs it in 215 // blocking mode, waiting for it to be shut down. 216 func geth(ctx *cli.Context) error { 217 node := makeFullNode(ctx) 218 startNode(ctx, node) 219 node.Wait() 220 return nil 221 } 222 223 // startNode boots up the system node and all registered protocols, after which 224 // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the 225 // miner. 226 func startNode(ctx *cli.Context, stack *node.Node) { 227 // Start up the node itself 228 utils.StartNode(stack) 229 230 // Unlock any account specifically requested 231 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 232 233 passwords := utils.MakePasswordList(ctx) 234 unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",") 235 for i, account := range unlocks { 236 if trimmed := strings.TrimSpace(account); trimmed != "" { 237 unlockAccount(ctx, ks, trimmed, i, passwords) 238 } 239 } 240 // Register wallet event handlers to open and auto-derive wallets 241 events := make(chan accounts.WalletEvent, 16) 242 stack.AccountManager().Subscribe(events) 243 244 go func() { 245 // Create an chain state reader for self-derivation 246 rpcClient, err := stack.Attach() 247 if err != nil { 248 utils.Fatalf("Failed to attach to self: %v", err) 249 } 250 stateReader := ethclient.NewClient(rpcClient) 251 252 // Open any wallets already attached 253 for _, wallet := range stack.AccountManager().Wallets() { 254 if err := wallet.Open(""); err != nil { 255 log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err) 256 } 257 } 258 // Listen for wallet event till termination 259 for event := range events { 260 switch event.Kind { 261 case accounts.WalletArrived: 262 if err := event.Wallet.Open(""); err != nil { 263 log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err) 264 } 265 case accounts.WalletOpened: 266 status, _ := event.Wallet.Status() 267 log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status) 268 269 if event.Wallet.URL().Scheme == "ledger" { 270 event.Wallet.SelfDerive(accounts.DefaultLedgerBaseDerivationPath, stateReader) 271 } else { 272 event.Wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader) 273 } 274 275 case accounts.WalletDropped: 276 log.Info("Old wallet dropped", "url", event.Wallet.URL()) 277 event.Wallet.Close() 278 } 279 } 280 }() 281 // Start auxiliary services if enabled 282 if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) { 283 // Mining only makes sense if a full Ethereum node is running 284 if ctx.GlobalBool(utils.LightModeFlag.Name) || ctx.GlobalString(utils.SyncModeFlag.Name) == "light" { 285 utils.Fatalf("Light clients do not support mining") 286 } 287 var ethereum *eth.Ethereum 288 if err := stack.Service(ðereum); err != nil { 289 utils.Fatalf("Ethereum service not running: %v", err) 290 } 291 // Use a reduced number of threads if requested 292 if threads := ctx.GlobalInt(utils.MinerThreadsFlag.Name); threads > 0 { 293 type threaded interface { 294 SetThreads(threads int) 295 } 296 if th, ok := ethereum.Engine().(threaded); ok { 297 th.SetThreads(threads) 298 } 299 } 300 // Set the gas price to the limits from the CLI and start mining 301 ethereum.TxPool().SetGasPrice(utils.GlobalBig(ctx, utils.GasPriceFlag.Name)) 302 if err := ethereum.StartMining(true); err != nil { 303 utils.Fatalf("Failed to start mining: %v", err) 304 } 305 } 306 }