main.go 7.2 KB
Newer Older
F
Felix Lange 已提交
1 2 3 4 5 6 7 8 9 10
// Copyright 2014 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
F
Felix Lange 已提交
12 13 14
// GNU General Public License for more details.
//
// 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/>.
F
Felix Lange 已提交
16

17
// geth is the official command-line client for Ethereum.
18 19 20
package main

import (
O
obscuren 已提交
21 22
	"fmt"
	"os"
O
obscuren 已提交
23
	"runtime"
24
	"strings"
25
	"time"
O
obscuren 已提交
26

27
	"github.com/ethereum/go-ethereum/accounts"
28
	"github.com/ethereum/go-ethereum/accounts/keystore"
O
obscuren 已提交
29
	"github.com/ethereum/go-ethereum/cmd/utils"
Z
zelig 已提交
30
	"github.com/ethereum/go-ethereum/common"
31
	"github.com/ethereum/go-ethereum/console"
O
obscuren 已提交
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
)

Z
zelig 已提交
41
const (
42
	clientIdentifier = "geth" // Client identifier to advertise over the network
Z
zelig 已提交
43 44
)

45
var (
46 47 48 49 50 51
	// Git SHA1 commit hash of the release (set via linker flags)
	gitCommit = ""
	// Ethereum address of the Geth release oracle.
	relOracle = common.HexToAddress("0xfa7b9770ca4cb04296cac84f37736d4041251cdf")
	// The app that holds all commands and flags.
	app = utils.NewApp(gitCommit, "the go-ethereum command line interface")
52
)
53

54
func init() {
55
	// Initialize the CLI app and start Geth
56
	app.Action = geth
57
	app.HideVersion = true // we have a command to print the version
58
	app.Copyright = "Copyright 2013-2017 The go-ethereum Authors"
59
	app.Commands = []cli.Command{
60 61
		// See chaincmd.go:
		initCommand,
62 63 64 65
		importCommand,
		exportCommand,
		removedbCommand,
		dumpCommand,
66
		// See monitorcmd.go:
67
		monitorCommand,
68
		// See accountcmd.go:
69 70
		accountCommand,
		walletCommand,
71
		// See consolecmd.go:
72 73 74
		consoleCommand,
		attachCommand,
		javascriptCommand,
75 76 77
		// See misccmd.go:
		makedagCommand,
		versionCommand,
78
		bugCommand,
79
		licenseCommand,
80 81
		// See config.go
		dumpConfigCommand,
82
	}
83

84
	app.Flags = []cli.Flag{
85
		utils.IdentityFlag,
86
		utils.UnlockedAccountFlag,
Z
zelig 已提交
87
		utils.PasswordFileFlag,
88 89
		utils.BootnodesFlag,
		utils.DataDirFlag,
K
Kobi Gurkan 已提交
90
		utils.KeyStoreDirFlag,
91 92 93 94
		utils.EthashCacheDirFlag,
		utils.EthashCachesInMemoryFlag,
		utils.EthashCachesOnDiskFlag,
		utils.EthashDatasetDirFlag,
95
		utils.EthashDatasetsInMemoryFlag,
96
		utils.EthashDatasetsOnDiskFlag,
97
		utils.FastSyncFlag,
98
		utils.LightModeFlag,
99
		utils.SyncModeFlag,
100 101
		utils.LightServFlag,
		utils.LightPeersFlag,
102
		utils.LightKDFFlag,
103
		utils.CacheFlag,
104
		utils.TrieCacheGenFlag,
Z
CLI:  
zelig 已提交
105
		utils.JSpathFlag,
106 107
		utils.ListenPortFlag,
		utils.MaxPeersFlag,
108
		utils.MaxPendingPeersFlag,
Z
zelig 已提交
109
		utils.EtherbaseFlag,
110
		utils.GasPriceFlag,
111 112
		utils.MinerThreadsFlag,
		utils.MiningEnabledFlag,
113
		utils.TargetGasLimitFlag,
114
		utils.NATFlag,
115
		utils.NoDiscoverFlag,
116
		utils.DiscoveryV5Flag,
117
		utils.NetrestrictFlag,
118 119 120 121 122
		utils.NodeKeyFileFlag,
		utils.NodeKeyHexFlag,
		utils.RPCEnabledFlag,
		utils.RPCListenAddrFlag,
		utils.RPCPortFlag,
123 124 125 126 127
		utils.RPCApiFlag,
		utils.WSEnabledFlag,
		utils.WSListenAddrFlag,
		utils.WSPortFlag,
		utils.WSApiFlag,
B
Bas van Kervel 已提交
128
		utils.WSAllowedOriginsFlag,
B
Bas van Kervel 已提交
129 130
		utils.IPCDisabledFlag,
		utils.IPCPathFlag,
131
		utils.ExecFlag,
132
		utils.PreloadJSFlag,
133
		utils.WhisperEnabledFlag,
134
		utils.DevModeFlag,
135
		utils.TestNetFlag,
136
		utils.VMEnableDebugFlag,
Z
zelig 已提交
137
		utils.NetworkIdFlag,
138
		utils.RPCCORSDomainFlag,
139
		utils.EthStatsURLFlag,
140
		utils.MetricsEnabledFlag,
141
		utils.FakePoWFlag,
142
		utils.NoCompactionFlag,
143 144
		utils.GpoBlocksFlag,
		utils.GpoPercentileFlag,
Z
zelig 已提交
145
		utils.ExtraDataFlag,
146
		configFileFlag,
147
	}
148 149
	app.Flags = append(app.Flags, debug.Flags...)

150
	app.Before = func(ctx *cli.Context) error {
151
		runtime.GOMAXPROCS(runtime.NumCPU())
152 153 154 155 156
		if err := debug.Setup(ctx); err != nil {
			return err
		}
		// Start system runtime metrics collection
		go metrics.CollectProcessMetrics(3 * time.Second)
157

158
		utils.SetupNetwork(ctx)
159
		return nil
160
	}
161 162 163

	app.After = func(ctx *cli.Context) error {
		debug.Exit()
164
		console.Stdin.Close() // Resets terminal mode.
165 166
		return nil
	}
167
}
O
obscuren 已提交
168

169 170 171 172 173 174
func main() {
	if err := app.Run(os.Args); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
Z
zelig 已提交
175

176 177 178
// geth is the main entry point into the system if no special subcommand is ran.
// It creates a default node based on the command line arguments and runs it in
// blocking mode, waiting for it to be shut down.
179
func geth(ctx *cli.Context) error {
180
	node := makeFullNode(ctx)
181 182
	startNode(ctx, node)
	node.Wait()
183
	return nil
184
}
185

186 187 188 189 190 191
// startNode boots up the system node and all registered protocols, after which
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
// miner.
func startNode(ctx *cli.Context, stack *node.Node) {
	// Start up the node itself
	utils.StartNode(stack)
192

193
	// Unlock any account specifically requested
194
	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
195

196
	passwords := utils.MakePasswordList(ctx)
197 198
	unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
	for i, account := range unlocks {
199
		if trimmed := strings.TrimSpace(account); trimmed != "" {
200
			unlockAccount(ctx, ks, trimmed, i, passwords)
Z
zelig 已提交
201
		}
Z
zelig 已提交
202
	}
203 204 205 206 207 208 209 210
	// Register wallet event handlers to open and auto-derive wallets
	events := make(chan accounts.WalletEvent, 16)
	stack.AccountManager().Subscribe(events)

	go func() {
		// Create an chain state reader for self-derivation
		rpcClient, err := stack.Attach()
		if err != nil {
211
			utils.Fatalf("Failed to attach to self: %v", err)
212 213 214
		}
		stateReader := ethclient.NewClient(rpcClient)

215 216 217
		// Open and self derive any wallets already attached
		for _, wallet := range stack.AccountManager().Wallets() {
			if err := wallet.Open(""); err != nil {
P
Péter Szilágyi 已提交
218
				log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err)
219 220
			} else {
				wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader)
221 222
			}
		}
223 224 225 226
		// Listen for wallet event till termination
		for event := range events {
			if event.Arrive {
				if err := event.Wallet.Open(""); err != nil {
P
Péter Szilágyi 已提交
227
					log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err)
228
				} else {
P
Péter Szilágyi 已提交
229
					log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", event.Wallet.Status())
230
					event.Wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader)
231 232
				}
			} else {
P
Péter Szilágyi 已提交
233
				log.Info("Old wallet dropped", "url", event.Wallet.URL())
234
				event.Wallet.Close()
235 236 237
			}
		}
	}()
238
	// Start auxiliary services if enabled
239
	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
240
		var ethereum *eth.Ethereum
241
		if err := stack.Service(&ethereum); err != nil {
242
			utils.Fatalf("ethereum service not running: %v", err)
243
		}
244 245 246 247 248 249 250 251
		if threads := ctx.GlobalInt(utils.MinerThreadsFlag.Name); threads > 0 {
			type threaded interface {
				SetThreads(threads int)
			}
			if th, ok := ethereum.Engine().(threaded); ok {
				th.SetThreads(threads)
			}
		}
252
		if err := ethereum.StartMining(true); err != nil {
253
			utils.Fatalf("Failed to start mining: %v", err)
254
		}
255 256
	}
}