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/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
	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
	versionPatch     = 14           // Patch version component of the current release
	versionMeta      = "prerelease" // 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 153
		utils.BootnodesFlag,
		utils.DataDirFlag,
K
Kobi Gurkan 已提交
154
		utils.KeyStoreDirFlag,
155
		utils.BlockchainVersionFlag,
156
		utils.OlympicFlag,
157
		utils.FastSyncFlag,
158
		utils.CacheFlag,
159
		utils.LightKDFFlag,
Z
CLI:  
zelig 已提交
160
		utils.JSpathFlag,
161 162
		utils.ListenPortFlag,
		utils.MaxPeersFlag,
163
		utils.MaxPendingPeersFlag,
Z
zelig 已提交
164
		utils.EtherbaseFlag,
165
		utils.GasPriceFlag,
166 167
		utils.SupportDAOFork,
		utils.OpposeDAOFork,
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

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
		return nil
229
	}
230 231 232 233

	app.After = func(ctx *cli.Context) error {
		logger.Flush()
		debug.Exit()
234
		console.Stdin.Close() // Resets terminal mode.
235 236
		return nil
	}
237
}
O
obscuren 已提交
238

239 240 241 242 243 244
func main() {
	if err := app.Run(os.Args); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
Z
zelig 已提交
245

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

266 267 268
// 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.
269
func geth(ctx *cli.Context) error {
270
	node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
271 272
	startNode(ctx, node)
	node.Wait()
273 274

	return nil
275
}
276

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

303 304 305 306 307 308
// 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)
309

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

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

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

362
func gpuinfo(ctx *cli.Context) error {
363
	eth.PrintOpenCLDevices()
364
	return nil
365 366
}

367
func gpubench(ctx *cli.Context) error {
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
	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()
	}
384
	return nil
385 386
}

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

	return nil
O
obscuren 已提交
398
}