main.go 11.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 (
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/core"
O
obscuren 已提交
36
	"github.com/ethereum/go-ethereum/eth"
37
	"github.com/ethereum/go-ethereum/ethdb"
38
	"github.com/ethereum/go-ethereum/internal/debug"
O
obscuren 已提交
39
	"github.com/ethereum/go-ethereum/logger"
40
	"github.com/ethereum/go-ethereum/logger/glog"
41
	"github.com/ethereum/go-ethereum/metrics"
42
	"github.com/ethereum/go-ethereum/node"
43
	"github.com/ethereum/go-ethereum/params"
44
	"github.com/ethereum/go-ethereum/release"
45
	"github.com/ethereum/go-ethereum/rlp"
46
	"gopkg.in/urfave/cli.v1"
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
		consoleCommand,
		attachCommand,
		javascriptCommand,
101 102 103 104 105 106 107 108 109
		{
			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.
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
`,
		},
		{
			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.
126 127
`,
		},
128 129 130 131 132 133 134 135
		{
			Action: version,
			Name:   "version",
			Usage:  "print ethereum version numbers",
			Description: `
The output of this command is supposed to be machine-readable.
`,
		},
136 137 138 139 140 141 142 143
		{
			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.
144 145 146
`,
		},
	}
147

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

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

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

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

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

233
		return nil
234
	}
235 236 237 238

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

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

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

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

	return nil
280
}
281

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

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

315 316
	// Unlock any account specifically requested
	var ethereum *eth.Ethereum
317
	if err := stack.Service(&ethereum); err != nil {
318
		utils.Fatalf("ethereum service not running: %v", err)
319
	}
320 321
	accman := ethereum.AccountManager()
	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 332
		if err := ethereum.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name), ctx.GlobalString(utils.MiningGPUFlag.Name)); err != nil {
			utils.Fatalf("Failed to start mining: %v", err)
333
		}
334 335
	}
}
O
Merge  
obscuren 已提交
336

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

367
func gpuinfo(ctx *cli.Context) error {
368
	eth.PrintOpenCLDevices()
369
	return nil
370 371
}

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

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

	return nil
O
obscuren 已提交
403
}