main.go 11.1 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/codegangsta/cli"
32
	"github.com/ethereum/ethash"
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 48
)

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

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

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

280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
// 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())
}

305 306 307 308 309 310
// 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)
311

312 313
	// Unlock any account specifically requested
	var ethereum *eth.Ethereum
314
	if err := stack.Service(&ethereum); err != nil {
315
		utils.Fatalf("ethereum service not running: %v", err)
316
	}
317 318
	accman := ethereum.AccountManager()
	passwords := utils.MakePasswordList(ctx)
Z
zelig 已提交
319

320
	accounts := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
321
	for i, account := range accounts {
322 323
		if trimmed := strings.TrimSpace(account); trimmed != "" {
			unlockAccount(ctx, accman, trimmed, i, passwords)
Z
zelig 已提交
324
		}
Z
zelig 已提交
325
	}
326
	// Start auxiliary services if enabled
327
	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
328 329
		if err := ethereum.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name), ctx.GlobalString(utils.MiningGPUFlag.Name)); err != nil {
			utils.Fatalf("Failed to start mining: %v", err)
330
		}
331 332
	}
}
O
Merge  
obscuren 已提交
333

334
func makedag(ctx *cli.Context) {
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
	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()
	}
361 362
}

363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
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()
	}
}

386
func version(c *cli.Context) {
387
	fmt.Println(clientIdentifier)
388
	fmt.Println("Version:", verString)
389
	fmt.Println("Protocol Versions:", eth.ProtocolVersions)
390 391 392 393 394
	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 已提交
395
}