main.go 10.8 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 (
21
	"encoding/hex"
O
obscuren 已提交
22
	"fmt"
23
	"io/ioutil"
O
obscuren 已提交
24
	"os"
25
	"path/filepath"
O
obscuren 已提交
26
	"runtime"
27
	"strconv"
28
	"strings"
29
	"time"
O
obscuren 已提交
30

31
	"github.com/ethereum/ethash"
O
obscuren 已提交
32
	"github.com/ethereum/go-ethereum/cmd/utils"
Z
zelig 已提交
33
	"github.com/ethereum/go-ethereum/common"
34
	"github.com/ethereum/go-ethereum/console"
35
	"github.com/ethereum/go-ethereum/contracts/release"
36
	"github.com/ethereum/go-ethereum/core"
37
	"github.com/ethereum/go-ethereum/core/state"
O
obscuren 已提交
38
	"github.com/ethereum/go-ethereum/eth"
39
	"github.com/ethereum/go-ethereum/internal/debug"
O
obscuren 已提交
40
	"github.com/ethereum/go-ethereum/logger"
41
	"github.com/ethereum/go-ethereum/logger/glog"
42
	"github.com/ethereum/go-ethereum/metrics"
43
	"github.com/ethereum/go-ethereum/node"
44
	"gopkg.in/urfave/cli.v1"
45 46
)

Z
zelig 已提交
47
const (
48
	clientIdentifier = "geth" // Client identifier to advertise over the network
Z
zelig 已提交
49 50
)

51
var (
52 53 54 55 56 57
	// 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")
58
)
59

60
func init() {
61
	// Initialize the CLI app and start Geth
62
	app.Action = geth
63
	app.HideVersion = true // we have a command to print the version
64
	app.Copyright = "Copyright 2013-2016 The go-ethereum Authors"
65
	app.Commands = []cli.Command{
66 67 68 69 70
		importCommand,
		exportCommand,
		upgradedbCommand,
		removedbCommand,
		dumpCommand,
71
		monitorCommand,
72 73
		accountCommand,
		walletCommand,
74 75 76
		consoleCommand,
		attachCommand,
		javascriptCommand,
77
		{
78 79 80 81 82
			Action:    makedag,
			Name:      "makedag",
			Usage:     "Generate ethash DAG (for testing)",
			ArgsUsage: "<blockNum> <outputDir>",
			Category:  "MISCELLANEOUS COMMANDS",
83 84 85 86 87 88 89
			Description: `
The makedag command generates an ethash DAG in /tmp/dag.

This command exists to support the system testing project.
Regular users do not need to execute it.
`,
		},
90
		{
91 92 93 94 95
			Action:    version,
			Name:      "version",
			Usage:     "Print version numbers",
			ArgsUsage: " ",
			Category:  "MISCELLANEOUS COMMANDS",
96 97 98 99
			Description: `
The output of this command is supposed to be machine-readable.
`,
		},
100
		{
101 102 103 104 105
			Action:    initGenesis,
			Name:      "init",
			Usage:     "Bootstrap and initialize a new genesis block",
			ArgsUsage: "<genesisPath>",
			Category:  "BLOCKCHAIN COMMANDS",
106
			Description: `
107
The init command initializes a new genesis block and definition for the network.
108 109
This is a destructive action and changes the network in which you will be
participating.
110 111
`,
		},
112
		{
113 114 115 116 117
			Action:    license,
			Name:      "license",
			Usage:     "Display license information",
			ArgsUsage: " ",
			Category:  "MISCELLANEOUS COMMANDS",
118
		},
119
	}
120

121
	app.Flags = []cli.Flag{
122
		utils.IdentityFlag,
123
		utils.UnlockedAccountFlag,
Z
zelig 已提交
124
		utils.PasswordFileFlag,
125 126
		utils.BootnodesFlag,
		utils.DataDirFlag,
K
Kobi Gurkan 已提交
127
		utils.KeyStoreDirFlag,
128
		utils.OlympicFlag,
129
		utils.FastSyncFlag,
130 131 132
		utils.LightModeFlag,
		utils.LightServFlag,
		utils.LightPeersFlag,
133
		utils.LightKDFFlag,
134
		utils.CacheFlag,
135
		utils.TrieCacheGenFlag,
Z
CLI:  
zelig 已提交
136
		utils.JSpathFlag,
137 138
		utils.ListenPortFlag,
		utils.MaxPeersFlag,
139
		utils.MaxPendingPeersFlag,
Z
zelig 已提交
140
		utils.EtherbaseFlag,
141
		utils.GasPriceFlag,
142 143
		utils.SupportDAOFork,
		utils.OpposeDAOFork,
144 145
		utils.MinerThreadsFlag,
		utils.MiningEnabledFlag,
146
		utils.AutoDAGFlag,
147
		utils.TargetGasLimitFlag,
148
		utils.NATFlag,
149
		utils.NatspecEnabledFlag,
150
		utils.NoDiscoverFlag,
151
		utils.DiscoveryV5Flag,
152 153 154 155 156
		utils.NodeKeyFileFlag,
		utils.NodeKeyHexFlag,
		utils.RPCEnabledFlag,
		utils.RPCListenAddrFlag,
		utils.RPCPortFlag,
157 158 159 160 161
		utils.RPCApiFlag,
		utils.WSEnabledFlag,
		utils.WSListenAddrFlag,
		utils.WSPortFlag,
		utils.WSApiFlag,
B
Bas van Kervel 已提交
162
		utils.WSAllowedOriginsFlag,
B
Bas van Kervel 已提交
163 164 165
		utils.IPCDisabledFlag,
		utils.IPCApiFlag,
		utils.IPCPathFlag,
166
		utils.ExecFlag,
167
		utils.PreloadJSFlag,
168
		utils.WhisperEnabledFlag,
169
		utils.DevModeFlag,
170
		utils.TestNetFlag,
171 172 173
		utils.VMForceJitFlag,
		utils.VMJitCacheFlag,
		utils.VMEnableJitFlag,
Z
zelig 已提交
174
		utils.NetworkIdFlag,
175
		utils.RPCCORSDomainFlag,
176
		utils.MetricsEnabledFlag,
177
		utils.FakePoWFlag,
178
		utils.SolcPathFlag,
Z
zsfelfoldi 已提交
179 180 181 182 183 184
		utils.GpoMinGasPriceFlag,
		utils.GpoMaxGasPriceFlag,
		utils.GpoFullBlockRatioFlag,
		utils.GpobaseStepDownFlag,
		utils.GpobaseStepUpFlag,
		utils.GpobaseCorrectionFactorFlag,
Z
zelig 已提交
185
		utils.ExtraDataFlag,
186
	}
187 188
	app.Flags = append(app.Flags, debug.Flags...)

189
	app.Before = func(ctx *cli.Context) error {
190
		runtime.GOMAXPROCS(runtime.NumCPU())
191 192 193 194 195
		if err := debug.Setup(ctx); err != nil {
			return err
		}
		// Start system runtime metrics collection
		go metrics.CollectProcessMetrics(3 * time.Second)
196

F
Felix Lange 已提交
197 198 199 200 201 202
		// This should be the only place where reporting is enabled
		// because it is not intended to run while testing.
		// In addition to this check, bad block reports are sent only
		// for chains with the main network genesis block and network id 1.
		eth.EnableBadBlockReporting = true

203
		utils.SetupNetwork(ctx)
204
		return nil
205
	}
206 207 208 209

	app.After = func(ctx *cli.Context) error {
		logger.Flush()
		debug.Exit()
210
		console.Stdin.Close() // Resets terminal mode.
211 212
		return nil
	}
213
}
O
obscuren 已提交
214

215 216 217 218 219 220
func main() {
	if err := app.Run(os.Args); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
Z
zelig 已提交
221

222 223 224
// 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.
225
func geth(ctx *cli.Context) error {
226
	node := makeFullNode(ctx)
227 228
	startNode(ctx, node)
	node.Wait()
229
	return nil
230
}
231

232 233
// initGenesis will initialise the given JSON format genesis file and writes it as
// the zero'd block (i.e. genesis) or will fail hard if it can't succeed.
234
func initGenesis(ctx *cli.Context) error {
235 236 237 238 239
	genesisPath := ctx.Args().First()
	if len(genesisPath) == 0 {
		utils.Fatalf("must supply path to genesis JSON file")
	}

240 241 242 243
	if ctx.GlobalBool(utils.TestNetFlag.Name) {
		state.StartingNonce = 1048576 // (2**20)
	}

244 245
	stack := makeFullNode(ctx)
	chaindb := utils.MakeChainDatabase(ctx, stack)
246 247 248 249 250 251

	genesisFile, err := os.Open(genesisPath)
	if err != nil {
		utils.Fatalf("failed to read genesis file: %v", err)
	}

252
	block, err := core.WriteGenesisBlock(chaindb, genesisFile)
253 254 255 256
	if err != nil {
		utils.Fatalf("failed to write genesis block: %v", err)
	}
	glog.V(logger.Info).Infof("successfully wrote genesis block and/or chain rule set: %x", block.Hash())
257
	return nil
258 259
}

260
func makeFullNode(ctx *cli.Context) *node.Node {
261 262 263
	stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
	utils.RegisterEthService(ctx, stack, utils.MakeDefaultExtraData(clientIdentifier))

264 265 266 267
	// Whisper must be explicitly enabled, but is auto-enabled in --dev mode.
	shhEnabled := ctx.GlobalBool(utils.WhisperEnabledFlag.Name)
	shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DevModeFlag.Name)
	if shhEnabled || shhAutoEnabled {
268
		utils.RegisterShhService(stack)
269 270
	}

271 272 273 274 275 276 277 278 279 280 281 282 283
	// Add the release oracle service so it boots along with node.
	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
		config := release.Config{
			Oracle: relOracle,
			Major:  uint32(utils.VersionMajor),
			Minor:  uint32(utils.VersionMinor),
			Patch:  uint32(utils.VersionPatch),
		}
		commit, _ := hex.DecodeString(gitCommit)
		copy(config.Commit[:], commit)
		return release.NewReleaseService(ctx, config)
	}); err != nil {
		utils.Fatalf("Failed to register the Geth release oracle service: %v", err)
284 285
	}

286
	return stack
287 288
}

289 290 291 292 293 294
// 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)
295

296
	// Unlock any account specifically requested
297
	accman := stack.AccountManager()
298 299
	passwords := utils.MakePasswordList(ctx)
	accounts := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
300
	for i, account := range accounts {
301 302
		if trimmed := strings.TrimSpace(account); trimmed != "" {
			unlockAccount(ctx, accman, trimmed, i, passwords)
Z
zelig 已提交
303
		}
Z
zelig 已提交
304
	}
305
	// Start auxiliary services if enabled
306
	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
307
		var ethereum *eth.Ethereum
308 309 310
		if err := stack.Service(&ethereum); err != nil {
			utils.Fatalf("ethereum service not running: %v", err)
		}
311
		if err := ethereum.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name)); err != nil {
312
			utils.Fatalf("Failed to start mining: %v", err)
313
		}
314 315
	}
}
O
Merge  
obscuren 已提交
316

317
func makedag(ctx *cli.Context) error {
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
	args := ctx.Args()
	wrongArgs := func() {
		utils.Fatalf(`Usage: geth makedag <block number> <outputdir>`)
	}
	switch {
	case len(args) == 2:
		blockNum, err := strconv.ParseUint(args[0], 0, 64)
		dir := args[1]
		if err != nil {
			wrongArgs()
		} else {
			dir = filepath.Clean(dir)
			// seems to require a trailing slash
			if !strings.HasSuffix(dir, "/") {
				dir = dir + "/"
			}
			_, err = ioutil.ReadDir(dir)
			if err != nil {
				utils.Fatalf("Can't find dir")
			}
			fmt.Println("making DAG, this could take awhile...")
			ethash.MakeDAG(blockNum, dir)
		}
	default:
		wrongArgs()
	}
344
	return nil
345 346
}

347
func version(ctx *cli.Context) error {
348
	fmt.Println(strings.Title(clientIdentifier))
349 350 351 352
	fmt.Println("Version:", utils.Version)
	if gitCommit != "" {
		fmt.Println("Git Commit:", gitCommit)
	}
353
	fmt.Println("Protocol Versions:", eth.ProtocolVersions)
354
	fmt.Println("Network Id:", ctx.GlobalInt(utils.NetworkIdFlag.Name))
355 356 357 358
	fmt.Println("Go Version:", runtime.Version())
	fmt.Println("OS:", runtime.GOOS)
	fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH"))
	fmt.Printf("GOROOT=%s\n", runtime.GOROOT())
359
	return nil
O
obscuren 已提交
360
}
361

362
func license(_ *cli.Context) error {
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
	fmt.Println(`Geth 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.

Geth is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with geth. If not, see <http://www.gnu.org/licenses/>.
`)
	return nil
}