main.go 11.4 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"
32
	"github.com/ethereum/go-ethereum/accounts"
O
obscuren 已提交
33
	"github.com/ethereum/go-ethereum/cmd/utils"
Z
zelig 已提交
34
	"github.com/ethereum/go-ethereum/common"
35
	"github.com/ethereum/go-ethereum/console"
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
	"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
	app.Flags = []cli.Flag{
150
		utils.IdentityFlag,
151
		utils.UnlockedAccountFlag,
Z
zelig 已提交
152
		utils.PasswordFileFlag,
153
		utils.GenesisFileFlag,
154 155
		utils.BootnodesFlag,
		utils.DataDirFlag,
K
Kobi Gurkan 已提交
156
		utils.KeyStoreDirFlag,
157
		utils.BlockchainVersionFlag,
158
		utils.OlympicFlag,
159
		utils.FastSyncFlag,
160
		utils.CacheFlag,
161
		utils.LightKDFFlag,
Z
CLI:  
zelig 已提交
162
		utils.JSpathFlag,
163 164
		utils.ListenPortFlag,
		utils.MaxPeersFlag,
165
		utils.MaxPendingPeersFlag,
Z
zelig 已提交
166
		utils.EtherbaseFlag,
167
		utils.GasPriceFlag,
168 169
		utils.MinerThreadsFlag,
		utils.MiningEnabledFlag,
170
		utils.MiningGPUFlag,
171
		utils.AutoDAGFlag,
172
		utils.TargetGasLimitFlag,
173
		utils.NATFlag,
174
		utils.NatspecEnabledFlag,
175
		utils.NoDiscoverFlag,
176 177 178 179 180
		utils.NodeKeyFileFlag,
		utils.NodeKeyHexFlag,
		utils.RPCEnabledFlag,
		utils.RPCListenAddrFlag,
		utils.RPCPortFlag,
181 182 183 184 185
		utils.RPCApiFlag,
		utils.WSEnabledFlag,
		utils.WSListenAddrFlag,
		utils.WSPortFlag,
		utils.WSApiFlag,
B
Bas van Kervel 已提交
186
		utils.WSAllowedOriginsFlag,
B
Bas van Kervel 已提交
187 188 189
		utils.IPCDisabledFlag,
		utils.IPCApiFlag,
		utils.IPCPathFlag,
190
		utils.ExecFlag,
191
		utils.PreloadJSFlag,
192
		utils.WhisperEnabledFlag,
193
		utils.DevModeFlag,
194
		utils.TestNetFlag,
195 196 197
		utils.VMForceJitFlag,
		utils.VMJitCacheFlag,
		utils.VMEnableJitFlag,
Z
zelig 已提交
198
		utils.NetworkIdFlag,
199
		utils.RPCCORSDomainFlag,
200
		utils.MetricsEnabledFlag,
201
		utils.FakePoWFlag,
202
		utils.SolcPathFlag,
Z
zsfelfoldi 已提交
203 204 205 206 207 208
		utils.GpoMinGasPriceFlag,
		utils.GpoMaxGasPriceFlag,
		utils.GpoFullBlockRatioFlag,
		utils.GpobaseStepDownFlag,
		utils.GpobaseStepUpFlag,
		utils.GpobaseCorrectionFactorFlag,
Z
zelig 已提交
209
		utils.ExtraDataFlag,
210
	}
211 212
	app.Flags = append(app.Flags, debug.Flags...)

213
	app.Before = func(ctx *cli.Context) error {
214
		runtime.GOMAXPROCS(runtime.NumCPU())
215 216 217 218 219
		if err := debug.Setup(ctx); err != nil {
			return err
		}
		// Start system runtime metrics collection
		go metrics.CollectProcessMetrics(3 * time.Second)
220

F
Felix Lange 已提交
221 222 223 224 225 226
		// 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

227
		utils.SetupNetwork(ctx)
228 229 230 231 232 233

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

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 255 256 257
func makeDefaultExtra() []byte {
	var clientInfo = struct {
		Version   uint
		Name      string
		GoVersion string
		Os        string
258
	}{uint(versionMajor<<16 | versionMinor<<8 | versionPatch), clientIdentifier, runtime.Version(), runtime.GOOS}
259 260 261 262 263 264 265 266 267 268 269 270 271
	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
}

272 273 274
// 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.
275
func geth(ctx *cli.Context) error {
276
	node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
277 278
	startNode(ctx, node)
	node.Wait()
279 280

	return nil
281
}
282

283 284
// 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.
285
func initGenesis(ctx *cli.Context) error {
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
	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())
306
	return nil
307 308
}

309 310 311 312 313 314
// 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)
315

316
	// Unlock any account specifically requested
317 318
	var accman *accounts.Manager
	if err := stack.Service(&accman); err != nil {
319
		utils.Fatalf("ethereum service not running: %v", err)
320
	}
321
	passwords := utils.MakePasswordList(ctx)
Z
zelig 已提交
322

323
	accounts := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
324
	for i, account := range accounts {
325 326
		if trimmed := strings.TrimSpace(account); trimmed != "" {
			unlockAccount(ctx, accman, trimmed, i, passwords)
Z
zelig 已提交
327
		}
Z
zelig 已提交
328
	}
329
	// Start auxiliary services if enabled
330
	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
331
		var ethereum *eth.Ethereum
332 333 334
		if err := stack.Service(&ethereum); err != nil {
			utils.Fatalf("ethereum service not running: %v", err)
		}
335 336
		if err := ethereum.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name), ctx.GlobalString(utils.MiningGPUFlag.Name)); err != nil {
			utils.Fatalf("Failed to start mining: %v", err)
337
		}
338 339
	}
}
O
Merge  
obscuren 已提交
340

341
func makedag(ctx *cli.Context) error {
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
	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()
	}
368
	return nil
369 370
}

371
func gpuinfo(ctx *cli.Context) error {
372
	eth.PrintOpenCLDevices()
373
	return nil
374 375
}

376
func gpubench(ctx *cli.Context) error {
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
	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()
	}
393
	return nil
394 395
}

396
func version(c *cli.Context) error {
397
	fmt.Println(clientIdentifier)
398
	fmt.Println("Version:", verString)
399
	fmt.Println("Protocol Versions:", eth.ProtocolVersions)
400 401 402 403 404
	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())
405 406

	return nil
O
obscuren 已提交
407
}