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