main.go 12.5 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/ethdb"
40
	"github.com/ethereum/go-ethereum/internal/debug"
O
obscuren 已提交
41
	"github.com/ethereum/go-ethereum/logger"
42
	"github.com/ethereum/go-ethereum/logger/glog"
43
	"github.com/ethereum/go-ethereum/metrics"
44
	"github.com/ethereum/go-ethereum/node"
45 46
	"github.com/ethereum/go-ethereum/params"
	"github.com/ethereum/go-ethereum/rlp"
47
	"gopkg.in/urfave/cli.v1"
48 49
)

Z
zelig 已提交
50
const (
51 52 53 54 55 56
	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

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

60
var (
61 62 63 64
	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
65
)
66

67
func init() {
68 69 70 71 72 73 74
	// 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]
75
	}
76 77
	// Construct the version release oracle configuration
	relConfig.Oracle = common.HexToAddress(versionOracle)
78

79 80 81 82 83 84 85 86 87
	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")
88
	app.Action = geth
89 90
	app.HideVersion = true // we have a command to print the version
	app.Commands = []cli.Command{
91 92 93 94 95
		importCommand,
		exportCommand,
		upgradedbCommand,
		removedbCommand,
		dumpCommand,
96
		monitorCommand,
97 98
		accountCommand,
		walletCommand,
99 100 101
		consoleCommand,
		attachCommand,
		javascriptCommand,
102 103 104 105 106 107 108 109 110
		{
			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.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
`,
		},
		{
			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.
127 128
`,
		},
129 130 131 132 133 134 135 136
		{
			Action: version,
			Name:   "version",
			Usage:  "print ethereum version numbers",
			Description: `
The output of this command is supposed to be machine-readable.
`,
		},
137 138 139 140 141 142 143 144
		{
			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.
145 146
`,
		},
147 148 149 150 151
		{
			Action: license,
			Name:   "license",
			Usage:  "displays geth's license information",
		},
152
	}
153

154
	app.Flags = []cli.Flag{
155
		utils.IdentityFlag,
156
		utils.UnlockedAccountFlag,
Z
zelig 已提交
157
		utils.PasswordFileFlag,
158 159
		utils.BootnodesFlag,
		utils.DataDirFlag,
K
Kobi Gurkan 已提交
160
		utils.KeyStoreDirFlag,
161
		utils.BlockchainVersionFlag,
162
		utils.OlympicFlag,
163
		utils.FastSyncFlag,
164
		utils.CacheFlag,
165
		utils.LightKDFFlag,
Z
CLI:  
zelig 已提交
166
		utils.JSpathFlag,
167 168
		utils.ListenPortFlag,
		utils.MaxPeersFlag,
169
		utils.MaxPendingPeersFlag,
Z
zelig 已提交
170
		utils.EtherbaseFlag,
171
		utils.GasPriceFlag,
172 173
		utils.SupportDAOFork,
		utils.OpposeDAOFork,
174 175
		utils.MinerThreadsFlag,
		utils.MiningEnabledFlag,
176
		utils.MiningGPUFlag,
177
		utils.AutoDAGFlag,
178
		utils.TargetGasLimitFlag,
179
		utils.NATFlag,
180
		utils.NatspecEnabledFlag,
181
		utils.NoDiscoverFlag,
182 183 184 185 186
		utils.NodeKeyFileFlag,
		utils.NodeKeyHexFlag,
		utils.RPCEnabledFlag,
		utils.RPCListenAddrFlag,
		utils.RPCPortFlag,
187 188 189 190 191
		utils.RPCApiFlag,
		utils.WSEnabledFlag,
		utils.WSListenAddrFlag,
		utils.WSPortFlag,
		utils.WSApiFlag,
B
Bas van Kervel 已提交
192
		utils.WSAllowedOriginsFlag,
B
Bas van Kervel 已提交
193 194 195
		utils.IPCDisabledFlag,
		utils.IPCApiFlag,
		utils.IPCPathFlag,
196
		utils.ExecFlag,
197
		utils.PreloadJSFlag,
198
		utils.WhisperEnabledFlag,
199
		utils.DevModeFlag,
200
		utils.TestNetFlag,
201 202 203
		utils.VMForceJitFlag,
		utils.VMJitCacheFlag,
		utils.VMEnableJitFlag,
Z
zelig 已提交
204
		utils.NetworkIdFlag,
205
		utils.RPCCORSDomainFlag,
206
		utils.MetricsEnabledFlag,
207
		utils.FakePoWFlag,
208
		utils.SolcPathFlag,
Z
zsfelfoldi 已提交
209 210 211 212 213 214
		utils.GpoMinGasPriceFlag,
		utils.GpoMaxGasPriceFlag,
		utils.GpoFullBlockRatioFlag,
		utils.GpobaseStepDownFlag,
		utils.GpobaseStepUpFlag,
		utils.GpobaseCorrectionFactorFlag,
Z
zelig 已提交
215
		utils.ExtraDataFlag,
216
	}
217 218
	app.Flags = append(app.Flags, debug.Flags...)

219
	app.Before = func(ctx *cli.Context) error {
220
		runtime.GOMAXPROCS(runtime.NumCPU())
221 222 223 224 225
		if err := debug.Setup(ctx); err != nil {
			return err
		}
		// Start system runtime metrics collection
		go metrics.CollectProcessMetrics(3 * time.Second)
226

F
Felix Lange 已提交
227 228 229 230 231 232
		// 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

233
		utils.SetupNetwork(ctx)
234
		return nil
235
	}
236 237 238 239

	app.After = func(ctx *cli.Context) error {
		logger.Flush()
		debug.Exit()
240
		console.Stdin.Close() // Resets terminal mode.
241 242
		return nil
	}
243
}
O
obscuren 已提交
244

245 246 247 248 249 250
func main() {
	if err := app.Run(os.Args); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
Z
zelig 已提交
251

252 253 254
// 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.
255
func geth(ctx *cli.Context) error {
256
	node := makeFullNode(ctx)
257 258
	startNode(ctx, node)
	node.Wait()
259
	return nil
260
}
261

262 263
// 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.
264
func initGenesis(ctx *cli.Context) error {
265 266 267 268 269
	genesisPath := ctx.Args().First()
	if len(genesisPath) == 0 {
		utils.Fatalf("must supply path to genesis JSON file")
	}

270 271 272 273
	if ctx.GlobalBool(utils.TestNetFlag.Name) {
		state.StartingNonce = 1048576 // (2**20)
	}

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
	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())
289
	return nil
290 291
}

292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
func makeFullNode(ctx *cli.Context) *node.Node {
	node := utils.MakeNode(ctx, clientIdentifier, verString)
	utils.RegisterEthService(ctx, node, relConfig, makeDefaultExtra())
	// 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 {
		utils.RegisterShhService(node)
	}
	return node
}

func makeDefaultExtra() []byte {
	var clientInfo = struct {
		Version   uint
		Name      string
		GoVersion string
		Os        string
	}{uint(versionMajor<<16 | versionMinor<<8 | versionPatch), clientIdentifier, runtime.Version(), runtime.GOOS}
	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
}

324 325 326 327
// 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) {
328 329
	// Report geth version
	glog.V(logger.Info).Infof("instance: Geth/%s/%s/%s\n", verString, runtime.Version(), runtime.GOOS)
330 331
	// Start up the node itself
	utils.StartNode(stack)
332

333
	// Unlock any account specifically requested
334
	accman := stack.AccountManager()
335 336
	passwords := utils.MakePasswordList(ctx)
	accounts := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
337
	for i, account := range accounts {
338 339
		if trimmed := strings.TrimSpace(account); trimmed != "" {
			unlockAccount(ctx, accman, trimmed, i, passwords)
Z
zelig 已提交
340
		}
Z
zelig 已提交
341
	}
342
	// Start auxiliary services if enabled
343
	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
344
		var ethereum *eth.Ethereum
345 346 347
		if err := stack.Service(&ethereum); err != nil {
			utils.Fatalf("ethereum service not running: %v", err)
		}
348 349
		if err := ethereum.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name), ctx.GlobalString(utils.MiningGPUFlag.Name)); err != nil {
			utils.Fatalf("Failed to start mining: %v", err)
350
		}
351 352
	}
}
O
Merge  
obscuren 已提交
353

354
func makedag(ctx *cli.Context) error {
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
	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()
	}
381
	return nil
382 383
}

384
func gpuinfo(ctx *cli.Context) error {
385
	eth.PrintOpenCLDevices()
386
	return nil
387 388
}

389
func gpubench(ctx *cli.Context) error {
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
	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()
	}
406
	return nil
407 408
}

409
func version(c *cli.Context) error {
410
	fmt.Println(clientIdentifier)
411
	fmt.Println("Version:", verString)
412
	fmt.Println("Protocol Versions:", eth.ProtocolVersions)
413 414 415 416 417
	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())
418 419

	return nil
O
obscuren 已提交
420
}
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438

func license(c *cli.Context) error {
	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
}