main.go 14.9 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
	"os/signal"
26
	"path/filepath"
O
obscuren 已提交
27
	"runtime"
28
	"strconv"
29
	"strings"
30
	"time"
O
obscuren 已提交
31

32
	"github.com/codegangsta/cli"
33
	"github.com/ethereum/ethash"
O
obscuren 已提交
34
	"github.com/ethereum/go-ethereum/cmd/utils"
Z
zelig 已提交
35
	"github.com/ethereum/go-ethereum/common"
36
	"github.com/ethereum/go-ethereum/core"
O
obscuren 已提交
37
	"github.com/ethereum/go-ethereum/eth"
38
	"github.com/ethereum/go-ethereum/ethdb"
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
	"github.com/ethereum/go-ethereum/params"
45
	"github.com/ethereum/go-ethereum/release"
46
	"github.com/ethereum/go-ethereum/rlp"
47 48
)

Z
zelig 已提交
49
const (
50 51 52 53 54 55
	clientIdentifier = "Geth"     // Client identifier to advertise over the network
	versionMajor     = 1          // Major version component of the current release
	versionMinor     = 5          // Minor version component of the current release
	versionPatch     = 0          // Patch version component of the current release
	versionMeta      = "unstable" // Version metadata to append to the version string

56
	versionOracle = "0xfa7b9770ca4cb04296cac84f37736d4041251cdf" // Ethereum address of the Geth release oracle
Z
zelig 已提交
57 58
)

59
var (
60 61 62 63
	gitCommit string         // Git SHA1 commit hash of the release (set via linker flags)
	verString string         // Combined textual representation of all the version components
	relConfig release.Config // Structured version information and release oracle config
	app       *cli.App
64
)
65

66
func init() {
67 68 69 70 71 72 73
	// Construct the textual version string from the individual components
	verString = fmt.Sprintf("%d.%d.%d", versionMajor, versionMinor, versionPatch)
	if versionMeta != "" {
		verString += "-" + versionMeta
	}
	if gitCommit != "" {
		verString += "-" + gitCommit[:8]
74
	}
75 76
	// Construct the version release oracle configuration
	relConfig.Oracle = common.HexToAddress(versionOracle)
77

78 79 80 81 82 83 84 85 86
	relConfig.Major = uint32(versionMajor)
	relConfig.Minor = uint32(versionMinor)
	relConfig.Patch = uint32(versionPatch)

	commit, _ := hex.DecodeString(gitCommit)
	copy(relConfig.Commit[:], commit)

	// Initialize the CLI app and start Geth
	app = utils.NewApp(verString, "the go-ethereum command line interface")
87
	app.Action = geth
88 89
	app.HideVersion = true // we have a command to print the version
	app.Commands = []cli.Command{
90 91 92 93 94
		importCommand,
		exportCommand,
		upgradedbCommand,
		removedbCommand,
		dumpCommand,
95
		monitorCommand,
96 97
		accountCommand,
		walletCommand,
98 99 100 101 102 103 104 105 106
		{
			Action: makedag,
			Name:   "makedag",
			Usage:  "generate ethash dag (for testing)",
			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.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
`,
		},
		{
			Action: gpuinfo,
			Name:   "gpuinfo",
			Usage:  "gpuinfo",
			Description: `
Prints OpenCL device info for all found GPUs.
`,
		},
		{
			Action: gpubench,
			Name:   "gpubench",
			Usage:  "benchmark GPU",
			Description: `
Runs quick benchmark on first GPU found.
123 124
`,
		},
125 126 127 128 129 130 131 132
		{
			Action: version,
			Name:   "version",
			Usage:  "print ethereum version numbers",
			Description: `
The output of this command is supposed to be machine-readable.
`,
		},
133 134 135 136 137 138 139 140 141 142
		{
			Action: initGenesis,
			Name:   "init",
			Usage:  "bootstraps and initialises a new genesis block (JSON)",
			Description: `
The init command initialises a new genesis block and definition for the network.
This is a destructive action and changes the network in which you will be
participating.
`,
		},
143
		{
Z
CLI:  
zelig 已提交
144 145
			Action: console,
			Name:   "console",
O
obscuren 已提交
146
			Usage:  `Geth Console: interactive JavaScript environment`,
Z
CLI:  
zelig 已提交
147
			Description: `
O
obscuren 已提交
148
The Geth console is an interactive shell for the JavaScript runtime environment
149 150
which exposes a node admin interface as well as the Ðapp JavaScript API.
See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
151 152
`,
		},
B
Bas van Kervel 已提交
153 154 155
		{
			Action: attach,
			Name:   "attach",
B
Bas van Kervel 已提交
156
			Usage:  `Geth Console: interactive JavaScript environment (connect to node)`,
B
Bas van Kervel 已提交
157
			Description: `
158 159 160 161 162
		The Geth console is an interactive shell for the JavaScript runtime environment
		which exposes a node admin interface as well as the Ðapp JavaScript API.
		See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console.
		This command allows to open a console on a running geth node.
		`,
Z
CLI:  
zelig 已提交
163 164
		},
		{
165
			Action: execScripts,
166
			Name:   "js",
O
obscuren 已提交
167
			Usage:  `executes the given JavaScript files in the Geth JavaScript VM`,
168
			Description: `
169
The JavaScript VM exposes a node admin interface as well as the Ðapp
Z
zelig 已提交
170
JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
171 172 173
`,
		},
	}
174

175
	app.Flags = []cli.Flag{
176
		utils.IdentityFlag,
177
		utils.UnlockedAccountFlag,
Z
zelig 已提交
178
		utils.PasswordFileFlag,
179
		utils.GenesisFileFlag,
180 181
		utils.BootnodesFlag,
		utils.DataDirFlag,
K
Kobi Gurkan 已提交
182
		utils.KeyStoreDirFlag,
183
		utils.BlockchainVersionFlag,
184
		utils.OlympicFlag,
185
		utils.FastSyncFlag,
186
		utils.CacheFlag,
187
		utils.LightKDFFlag,
Z
CLI:  
zelig 已提交
188
		utils.JSpathFlag,
189 190
		utils.ListenPortFlag,
		utils.MaxPeersFlag,
191
		utils.MaxPendingPeersFlag,
Z
zelig 已提交
192
		utils.EtherbaseFlag,
193
		utils.GasPriceFlag,
194 195
		utils.MinerThreadsFlag,
		utils.MiningEnabledFlag,
196
		utils.MiningGPUFlag,
197
		utils.AutoDAGFlag,
198
		utils.TargetGasLimitFlag,
199
		utils.NATFlag,
200
		utils.NatspecEnabledFlag,
201
		utils.NoDiscoverFlag,
202 203 204 205 206
		utils.NodeKeyFileFlag,
		utils.NodeKeyHexFlag,
		utils.RPCEnabledFlag,
		utils.RPCListenAddrFlag,
		utils.RPCPortFlag,
207 208 209 210 211
		utils.RPCApiFlag,
		utils.WSEnabledFlag,
		utils.WSListenAddrFlag,
		utils.WSPortFlag,
		utils.WSApiFlag,
B
Bas van Kervel 已提交
212
		utils.WSAllowedOriginsFlag,
B
Bas van Kervel 已提交
213 214 215
		utils.IPCDisabledFlag,
		utils.IPCApiFlag,
		utils.IPCPathFlag,
216
		utils.ExecFlag,
217
		utils.PreLoadJSFlag,
218
		utils.WhisperEnabledFlag,
219
		utils.DevModeFlag,
220
		utils.TestNetFlag,
221 222 223
		utils.VMForceJitFlag,
		utils.VMJitCacheFlag,
		utils.VMEnableJitFlag,
Z
zelig 已提交
224
		utils.NetworkIdFlag,
225
		utils.RPCCORSDomainFlag,
226
		utils.MetricsEnabledFlag,
227
		utils.FakePoWFlag,
228
		utils.SolcPathFlag,
Z
zsfelfoldi 已提交
229 230 231 232 233 234
		utils.GpoMinGasPriceFlag,
		utils.GpoMaxGasPriceFlag,
		utils.GpoFullBlockRatioFlag,
		utils.GpobaseStepDownFlag,
		utils.GpobaseStepUpFlag,
		utils.GpobaseCorrectionFactorFlag,
Z
zelig 已提交
235
		utils.ExtraDataFlag,
236
	}
237 238
	app.Flags = append(app.Flags, debug.Flags...)

239
	app.Before = func(ctx *cli.Context) error {
240
		runtime.GOMAXPROCS(runtime.NumCPU())
241 242 243 244 245
		if err := debug.Setup(ctx); err != nil {
			return err
		}
		// Start system runtime metrics collection
		go metrics.CollectProcessMetrics(3 * time.Second)
246

F
Felix Lange 已提交
247 248 249 250 251 252
		// 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

253
		utils.SetupNetwork(ctx)
254 255 256 257 258 259

		// Deprecation warning.
		if ctx.GlobalIsSet(utils.GenesisFileFlag.Name) {
			common.PrintDepricationWarning("--genesis is deprecated. Switch to use 'geth init /path/to/file'")
		}

260
		return nil
261
	}
262 263 264 265

	app.After = func(ctx *cli.Context) error {
		logger.Flush()
		debug.Exit()
266
		utils.Stdin.Close() // Resets terminal mode.
267 268
		return nil
	}
269
}
O
obscuren 已提交
270

271 272 273 274 275 276
func main() {
	if err := app.Run(os.Args); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
Z
zelig 已提交
277

278 279 280 281 282 283
func makeDefaultExtra() []byte {
	var clientInfo = struct {
		Version   uint
		Name      string
		GoVersion string
		Os        string
284
	}{uint(versionMajor<<16 | versionMinor<<8 | versionPatch), clientIdentifier, runtime.Version(), runtime.GOOS}
285 286 287 288 289 290 291 292 293 294 295 296 297
	extra, err := rlp.EncodeToBytes(clientInfo)
	if err != nil {
		glog.V(logger.Warn).Infoln("error setting canonical miner information:", err)
	}

	if uint64(len(extra)) > params.MaximumExtraDataSize.Uint64() {
		glog.V(logger.Warn).Infoln("error setting canonical miner information: extra exceeds", params.MaximumExtraDataSize)
		glog.V(logger.Debug).Infof("extra: %x\n", extra)
		return nil
	}
	return extra
}

298 299 300 301
// 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.
func geth(ctx *cli.Context) {
302
	node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
303 304
	startNode(ctx, node)
	node.Wait()
305
}
306

307
// attach will connect to a running geth instance attaching a JavaScript console and to it.
B
Bas van Kervel 已提交
308
func attach(ctx *cli.Context) {
309 310
	// attach to a running geth instance
	client, err := utils.NewRemoteRPCClient(ctx)
B
Bas van Kervel 已提交
311
	if err != nil {
312
		utils.Fatalf("Unable to attach to geth: %v", err)
B
Bas van Kervel 已提交
313 314 315
	}

	repl := newLightweightJSRE(
316
		ctx.GlobalString(utils.JSpathFlag.Name),
B
Bas van Kervel 已提交
317
		client,
B
Bas van Kervel 已提交
318
		ctx.GlobalString(utils.DataDirFlag.Name),
B
Bas van Kervel 已提交
319
		true,
B
Bas van Kervel 已提交
320
	)
B
Bas van Kervel 已提交
321

322 323 324 325 326 327 328
	// preload user defined JS files into the console
	err = repl.preloadJSFiles(ctx)
	if err != nil {
		utils.Fatalf("unable to preload JS file %v", err)
	}

	// in case the exec flag holds a JS statement execute it and return
329 330 331 332 333 334
	if ctx.GlobalString(utils.ExecFlag.Name) != "" {
		repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
	} else {
		repl.welcome()
		repl.interactive()
	}
B
Bas van Kervel 已提交
335 336
}

337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
// 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.
func initGenesis(ctx *cli.Context) {
	genesisPath := ctx.Args().First()
	if len(genesisPath) == 0 {
		utils.Fatalf("must supply path to genesis JSON file")
	}

	chainDb, err := ethdb.NewLDBDatabase(filepath.Join(utils.MustMakeDataDir(ctx), "chaindata"), 0, 0)
	if err != nil {
		utils.Fatalf("could not open database: %v", err)
	}

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

	block, err := core.WriteGenesisBlock(chainDb, genesisFile)
	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())
}

362 363
// console starts a new geth node, attaching a JavaScript console to it at the
// same time.
Z
CLI:  
zelig 已提交
364
func console(ctx *cli.Context) {
365
	// Create and start the node based on the CLI flags
366
	node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
367
	startNode(ctx, node)
368

369
	// Attach to the newly started node, and either execute script or become interactive
370
	client, err := node.Attach()
371 372 373
	if err != nil {
		utils.Fatalf("Failed to attach to the inproc geth: %v", err)
	}
374
	repl := newJSRE(node,
375
		ctx.GlobalString(utils.JSpathFlag.Name),
376
		ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
377
		client, true)
B
Bas van Kervel 已提交
378

379 380 381
	// preload user defined JS files into the console
	err = repl.preloadJSFiles(ctx)
	if err != nil {
382
		utils.Fatalf("%v", err)
383 384 385
	}

	// in case the exec flag holds a JS statement execute it and return
386 387
	if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" {
		repl.batch(script)
388 389 390 391
	} else {
		repl.welcome()
		repl.interactive()
	}
392
	node.Stop()
Z
CLI:  
zelig 已提交
393 394
}

395 396 397 398
// execScripts starts a new geth node based on the CLI flags, and executes each
// of the JavaScript files specified as command arguments.
func execScripts(ctx *cli.Context) {
	// Create and start the node based on the CLI flags
399
	node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
400
	startNode(ctx, node)
401
	defer node.Stop()
Z
CLI:  
zelig 已提交
402

403
	// Attach to the newly started node and execute the given scripts
404
	client, err := node.Attach()
405 406 407
	if err != nil {
		utils.Fatalf("Failed to attach to the inproc geth: %v", err)
	}
408
	repl := newJSRE(node,
409
		ctx.GlobalString(utils.JSpathFlag.Name),
410
		ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
411
		client, false)
412

413
	// Run all given files.
Z
CLI:  
zelig 已提交
414
	for _, file := range ctx.Args() {
415 416 417
		if err = repl.re.Exec(file); err != nil {
			break
		}
Z
CLI:  
zelig 已提交
418
	}
419 420 421 422 423 424 425 426 427 428 429 430
	if err != nil {
		utils.Fatalf("JavaScript Error: %v", jsErrorString(err))
	}
	// JS files loaded successfully.
	// Wait for pending callbacks, but stop for Ctrl-C.
	abort := make(chan os.Signal, 1)
	signal.Notify(abort, os.Interrupt)
	go func() {
		<-abort
		repl.re.Stop(false)
	}()
	repl.re.Stop(true)
431
}
O
obscuren 已提交
432

433 434 435 436 437 438
// 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)
439

440 441
	// Unlock any account specifically requested
	var ethereum *eth.Ethereum
442
	if err := stack.Service(&ethereum); err != nil {
443
		utils.Fatalf("ethereum service not running: %v", err)
444
	}
445 446
	accman := ethereum.AccountManager()
	passwords := utils.MakePasswordList(ctx)
Z
zelig 已提交
447

448
	accounts := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
449
	for i, account := range accounts {
450 451
		if trimmed := strings.TrimSpace(account); trimmed != "" {
			unlockAccount(ctx, accman, trimmed, i, passwords)
Z
zelig 已提交
452
		}
Z
zelig 已提交
453
	}
454
	// Start auxiliary services if enabled
455
	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
456 457
		if err := ethereum.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name), ctx.GlobalString(utils.MiningGPUFlag.Name)); err != nil {
			utils.Fatalf("Failed to start mining: %v", err)
458
		}
459 460
	}
}
O
Merge  
obscuren 已提交
461

462
func makedag(ctx *cli.Context) {
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
	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()
	}
489 490
}

491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
func gpuinfo(ctx *cli.Context) {
	eth.PrintOpenCLDevices()
}

func gpubench(ctx *cli.Context) {
	args := ctx.Args()
	wrongArgs := func() {
		utils.Fatalf(`Usage: geth gpubench <gpu number>`)
	}
	switch {
	case len(args) == 1:
		n, err := strconv.ParseUint(args[0], 0, 64)
		if err != nil {
			wrongArgs()
		}
		eth.GPUBench(n)
	case len(args) == 0:
		eth.GPUBench(0)
	default:
		wrongArgs()
	}
}

514
func version(c *cli.Context) {
515
	fmt.Println(clientIdentifier)
516
	fmt.Println("Version:", verString)
517
	fmt.Println("Protocol Versions:", eth.ProtocolVersions)
518 519 520 521 522
	fmt.Println("Network Id:", c.GlobalInt(utils.NetworkIdFlag.Name))
	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())
O
obscuren 已提交
523
}