flags.go 25.1 KB
Newer Older
F
Felix Lange 已提交
1 2 3 4 5 6 7 8 9 10
// Copyright 2015 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 18 19 20
package utils

import (
	"crypto/ecdsa"
21
	"fmt"
22
	"io/ioutil"
23
	"log"
24
	"math"
25
	"math/big"
B
Bas van Kervel 已提交
26
	"net"
27
	"net/http"
28
	"os"
29
	"path/filepath"
30
	"runtime"
31
	"strconv"
32
	"strings"
33

34
	"github.com/codegangsta/cli"
35
	"github.com/ethereum/ethash"
F
Felix Lange 已提交
36
	"github.com/ethereum/go-ethereum/accounts"
Z
zelig 已提交
37
	"github.com/ethereum/go-ethereum/common"
38
	"github.com/ethereum/go-ethereum/core"
39
	"github.com/ethereum/go-ethereum/core/state"
B
Bas van Kervel 已提交
40
	"github.com/ethereum/go-ethereum/core/vm"
41 42 43 44 45
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/eth"
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/event"
	"github.com/ethereum/go-ethereum/logger"
O
obscuren 已提交
46
	"github.com/ethereum/go-ethereum/logger/glog"
B
Bas van Kervel 已提交
47
	"github.com/ethereum/go-ethereum/metrics"
48 49
	"github.com/ethereum/go-ethereum/node"
	"github.com/ethereum/go-ethereum/p2p/discover"
50
	"github.com/ethereum/go-ethereum/p2p/nat"
51
	"github.com/ethereum/go-ethereum/params"
B
Bas van Kervel 已提交
52 53
	"github.com/ethereum/go-ethereum/rpc/api"
	"github.com/ethereum/go-ethereum/rpc/codec"
54
	"github.com/ethereum/go-ethereum/rpc/comms"
B
Bas van Kervel 已提交
55 56
	"github.com/ethereum/go-ethereum/rpc/shared"
	"github.com/ethereum/go-ethereum/rpc/useragent"
57
	"github.com/ethereum/go-ethereum/whisper"
58
	"github.com/ethereum/go-ethereum/xeth"
59 60
)

61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
func init() {
	cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]

VERSION:
   {{.Version}}

COMMANDS:
   {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
   {{end}}{{if .Flags}}
GLOBAL OPTIONS:
   {{range .Flags}}{{.}}
   {{end}}{{end}}
`

	cli.CommandHelpTemplate = `{{.Name}}{{if .Subcommands}} command{{end}}{{if .Flags}} [command options]{{end}} [arguments...]
{{if .Description}}{{.Description}}
{{end}}{{if .Subcommands}}
SUBCOMMANDS:
	{{range .Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
	{{end}}{{end}}{{if .Flags}}
OPTIONS:
	{{range .Flags}}{{.}}
	{{end}}{{end}}
`
}

F
Felix Lange 已提交
87 88 89
// NewApp creates an app with sane defaults.
func NewApp(version, usage string) *cli.App {
	app := cli.NewApp()
90
	app.Name = filepath.Base(os.Args[0])
F
Felix Lange 已提交
91
	app.Author = ""
O
obscuren 已提交
92
	//app.Authors = nil
F
Felix Lange 已提交
93 94 95 96 97 98
	app.Email = ""
	app.Version = version
	app.Usage = usage
	return app
}

99 100 101 102 103 104 105 106 107
// These are all the command line flags we support.
// If you add to this list, please remember to include the
// flag in the appropriate command definition.
//
// The flags are defined here so their names and help texts
// are the same for all commands.

var (
	// General settings
108
	DataDirFlag = DirectoryFlag{
109
		Name:  "datadir",
110
		Usage: "Data directory for the databases and keystore",
111
		Value: DirectoryString{common.DefaultDataDir()},
112
	}
Z
zelig 已提交
113 114
	NetworkIdFlag = cli.IntFlag{
		Name:  "networkid",
115
		Usage: "Network identifier (integer, 0=Olympic, 1=Frontier, 2=Morden)",
Z
zelig 已提交
116 117
		Value: eth.NetworkId,
	}
118 119 120
	OlympicFlag = cli.BoolFlag{
		Name:  "olympic",
		Usage: "Olympic network: pre-configured pre-release test network",
O
obscuren 已提交
121
	}
122 123 124
	TestNetFlag = cli.BoolFlag{
		Name:  "testnet",
		Usage: "Morden network: pre-configured test network with modified starting nonces (replay protection)",
125
	}
126 127
	DevModeFlag = cli.BoolFlag{
		Name:  "dev",
128
		Usage: "Developer mode: pre-configured private network with several debugging flags",
129
	}
130 131 132
	GenesisFileFlag = cli.StringFlag{
		Name:  "genesis",
		Usage: "Insert/overwrite the genesis block (JSON format)",
133
	}
134 135
	IdentityFlag = cli.StringFlag{
		Name:  "identity",
136
		Usage: "Custom node name",
137
	}
138 139 140 141
	NatspecEnabledFlag = cli.BoolFlag{
		Name:  "natspec",
		Usage: "Enable NatSpec confirmation notice",
	}
Z
zelig 已提交
142 143 144 145 146
	DocRootFlag = DirectoryFlag{
		Name:  "docroot",
		Usage: "Document Root for HTTPClient file scheme",
		Value: DirectoryString{common.HomeDir()},
	}
147 148
	CacheFlag = cli.IntFlag{
		Name:  "cache",
149
		Usage: "Megabytes of memory allocated to internal caching (min 16MB / database forced)",
150 151
		Value: 0,
	}
152 153 154 155
	BlockchainVersionFlag = cli.IntFlag{
		Name:  "blockchainversion",
		Usage: "Blockchain version (integer)",
		Value: core.BlockChainVersion,
156
	}
157 158
	FastSyncFlag = cli.BoolFlag{
		Name:  "fast",
159
		Usage: "Enable fast syncing through state downloads",
160
	}
161 162
	LightKDFFlag = cli.BoolFlag{
		Name:  "lightkdf",
163
		Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
164
	}
165
	// Miner settings
166
	// TODO: refactor CPU vs GPU mining flags
167 168 169
	MiningEnabledFlag = cli.BoolFlag{
		Name:  "mine",
		Usage: "Enable mining",
170
	}
171 172
	MinerThreadsFlag = cli.IntFlag{
		Name:  "minerthreads",
173
		Usage: "Number of CPU threads to use for mining",
174 175
		Value: runtime.NumCPU(),
	}
176 177 178
	MiningGPUFlag = cli.StringFlag{
		Name:  "minergpus",
		Usage: "List of GPUs to use for mining (e.g. '0,1' will use the first two GPUs found)",
179
	}
180 181 182 183
	AutoDAGFlag = cli.BoolFlag{
		Name:  "autodag",
		Usage: "Enable automatic DAG pregeneration",
	}
Z
zelig 已提交
184
	EtherbaseFlag = cli.StringFlag{
O
obscuren 已提交
185
		Name:  "etherbase",
186
		Usage: "Public address for block mining rewards (default = first account created)",
187
		Value: "0",
Z
zelig 已提交
188
	}
189 190
	GasPriceFlag = cli.StringFlag{
		Name:  "gasprice",
191
		Usage: "Minimal gas price to accept for mining a transactions",
192
		Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(),
193
	}
Z
zelig 已提交
194 195
	ExtraDataFlag = cli.StringFlag{
		Name:  "extradata",
196
		Usage: "Block extra data set by the miner (default = client version)",
Z
zelig 已提交
197
	}
198
	// Account settings
Z
zelig 已提交
199 200
	UnlockedAccountFlag = cli.StringFlag{
		Name:  "unlock",
201
		Usage: "Comma separated list of accounts to unlock",
Z
zelig 已提交
202 203 204 205
		Value: "",
	}
	PasswordFileFlag = cli.StringFlag{
		Name:  "password",
206
		Usage: "Password file to use for non-inteactive password input",
Z
zelig 已提交
207
		Value: "",
Z
zelig 已提交
208
	}
209

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
	// vm flags
	VMDebugFlag = cli.BoolFlag{
		Name:  "vmdebug",
		Usage: "Virtual Machine debug output",
	}
	VMForceJitFlag = cli.BoolFlag{
		Name:  "forcejit",
		Usage: "Force the JIT VM to take precedence",
	}
	VMJitCacheFlag = cli.IntFlag{
		Name:  "jitcache",
		Usage: "Amount of cached JIT VM programs",
		Value: 64,
	}
	VMEnableJitFlag = cli.BoolFlag{
		Name:  "jitvm",
		Usage: "Enable the JIT VM",
	}

Z
zelig 已提交
229
	// logging and debug settings
230 231
	VerbosityFlag = cli.IntFlag{
		Name:  "verbosity",
232
		Usage: "Logging verbosity: 0-6 (0=silent, 1=error, 2=warn, 3=info, 4=core, 5=debug, 6=debug detail)",
233 234
		Value: int(logger.InfoLevel),
	}
235 236 237
	LogFileFlag = cli.StringFlag{
		Name:  "logfile",
		Usage: "Log output file within the data dir (default = no log file generated)",
238
		Value: "",
239
	}
240 241
	LogVModuleFlag = cli.GenericFlag{
		Name:  "vmodule",
242
		Usage: "Per-module verbosity: comma-separated list of <module>=<level>, where <module> is file literal or a glog pattern",
243 244 245
		Value: glog.GetVModule(),
	}
	BacktraceAtFlag = cli.GenericFlag{
246 247
		Name:  "backtrace",
		Usage: "Request a stack trace at a specific logging statement (e.g. \"block.go:271\")",
248 249
		Value: glog.GetTraceLocation(),
	}
250 251
	PProfEanbledFlag = cli.BoolFlag{
		Name:  "pprof",
252
		Usage: "Enable the profiling server on localhost",
253 254 255
	}
	PProfPortFlag = cli.IntFlag{
		Name:  "pprofport",
256
		Usage: "Profile server listening port",
257 258
		Value: 6060,
	}
259 260
	MetricsEnabledFlag = cli.BoolFlag{
		Name:  metrics.MetricsEnabledFlag,
261
		Usage: "Enable metrics collection and reporting",
262
	}
263 264 265 266

	// RPC settings
	RPCEnabledFlag = cli.BoolFlag{
		Name:  "rpc",
267
		Usage: "Enable the HTTP-RPC server",
268 269 270
	}
	RPCListenAddrFlag = cli.StringFlag{
		Name:  "rpcaddr",
271
		Usage: "HTTP-RPC server listening interface",
272 273 274 275
		Value: "127.0.0.1",
	}
	RPCPortFlag = cli.IntFlag{
		Name:  "rpcport",
276
		Usage: "HTTP-RPC server listening port",
277 278
		Value: 8545,
	}
279 280
	RPCCORSDomainFlag = cli.StringFlag{
		Name:  "rpccorsdomain",
281
		Usage: "Domains from which to accept cross origin requests (browser enforced)",
282 283
		Value: "",
	}
284 285
	RpcApiFlag = cli.StringFlag{
		Name:  "rpcapi",
286
		Usage: "API's offered over the HTTP-RPC interface",
287
		Value: comms.DefaultHttpRpcApis,
288
	}
B
Bas van Kervel 已提交
289 290 291 292 293 294
	IPCDisabledFlag = cli.BoolFlag{
		Name:  "ipcdisable",
		Usage: "Disable the IPC-RPC server",
	}
	IPCApiFlag = cli.StringFlag{
		Name:  "ipcapi",
295
		Usage: "API's offered over the IPC-RPC interface",
296
		Value: comms.DefaultIpcApis,
B
Bas van Kervel 已提交
297 298 299 300 301 302
	}
	IPCPathFlag = DirectoryFlag{
		Name:  "ipcpath",
		Usage: "Filename for IPC socket/pipe",
		Value: DirectoryString{common.DefaultIpcPath()},
	}
303 304
	ExecFlag = cli.StringFlag{
		Name:  "exec",
305
		Usage: "Execute JavaScript statement (only in combination with console/attach)",
306
	}
307 308 309
	// Network Settings
	MaxPeersFlag = cli.IntFlag{
		Name:  "maxpeers",
310
		Usage: "Maximum number of network peers (network disabled if set to 0)",
311
		Value: 25,
312
	}
313 314 315 316 317
	MaxPendingPeersFlag = cli.IntFlag{
		Name:  "maxpendpeers",
		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
		Value: 0,
	}
318 319 320 321 322 323 324
	ListenPortFlag = cli.IntFlag{
		Name:  "port",
		Usage: "Network listening port",
		Value: 30303,
	}
	BootnodesFlag = cli.StringFlag{
		Name:  "bootnodes",
325
		Usage: "Comma separated enode URLs for P2P discovery bootstrap",
326 327 328 329 330 331 332 333 334 335 336 337
		Value: "",
	}
	NodeKeyFileFlag = cli.StringFlag{
		Name:  "nodekey",
		Usage: "P2P node key file",
	}
	NodeKeyHexFlag = cli.StringFlag{
		Name:  "nodekeyhex",
		Usage: "P2P node key as hex (for testing)",
	}
	NATFlag = cli.StringFlag{
		Name:  "nat",
338
		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
339 340
		Value: "any",
	}
341 342 343 344
	NoDiscoverFlag = cli.BoolFlag{
		Name:  "nodiscover",
		Usage: "Disables the peer discovery mechanism (manual peer addition)",
	}
345 346
	WhisperEnabledFlag = cli.BoolFlag{
		Name:  "shh",
347
		Usage: "Enable Whisper",
348
	}
349
	// ATM the url is left to the user and deployment to
Z
CLI:  
zelig 已提交
350 351
	JSpathFlag = cli.StringFlag{
		Name:  "jspath",
352
		Usage: "JavaSript root path for `loadScript` and document root for `admin.httpGet`",
Z
CLI:  
zelig 已提交
353 354
		Value: ".",
	}
355 356
	SolcPathFlag = cli.StringFlag{
		Name:  "solc",
357
		Usage: "Solidity compiler command to be used",
358 359
		Value: "solc",
	}
360 361

	// Gas price oracle settings
Z
zsfelfoldi 已提交
362 363 364
	GpoMinGasPriceFlag = cli.StringFlag{
		Name:  "gpomin",
		Usage: "Minimum suggested gas price",
365
		Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(),
Z
zsfelfoldi 已提交
366 367 368 369
	}
	GpoMaxGasPriceFlag = cli.StringFlag{
		Name:  "gpomax",
		Usage: "Maximum suggested gas price",
370
		Value: new(big.Int).Mul(big.NewInt(500), common.Shannon).String(),
Z
zsfelfoldi 已提交
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
	}
	GpoFullBlockRatioFlag = cli.IntFlag{
		Name:  "gpofull",
		Usage: "Full block threshold for gas price calculation (%)",
		Value: 80,
	}
	GpobaseStepDownFlag = cli.IntFlag{
		Name:  "gpobasedown",
		Usage: "Suggested gas price base step down ratio (1/1000)",
		Value: 10,
	}
	GpobaseStepUpFlag = cli.IntFlag{
		Name:  "gpobaseup",
		Usage: "Suggested gas price base step up ratio (1/1000)",
		Value: 100,
	}
	GpobaseCorrectionFactorFlag = cli.IntFlag{
		Name:  "gpobasecf",
		Usage: "Suggested gas price base correction factor (%)",
		Value: 110,
	}
392 393
)

394 395 396 397 398 399 400 401 402
// MustMakeDataDir retrieves the currently requested data directory, terminating
// if none (or the empty string) is specified. If the node is starting a testnet,
// the a subdirectory of the specified datadir will be used.
func MustMakeDataDir(ctx *cli.Context) string {
	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
		if ctx.GlobalBool(TestNetFlag.Name) {
			return filepath.Join(path, "/testnet")
		}
		return path
403
	}
404 405
	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
	return ""
406 407
}

408 409 410 411 412 413 414 415 416 417 418
// MakeNodeKey creates a node key from set command line flags, either loading it
// from a file or as a specified hex value. If neither flags were provided, this
// method returns nil and an emphemeral key is to be generated.
func MakeNodeKey(ctx *cli.Context) *ecdsa.PrivateKey {
	var (
		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
		file = ctx.GlobalString(NodeKeyFileFlag.Name)

		key *ecdsa.PrivateKey
		err error
	)
419 420 421
	switch {
	case file != "" && hex != "":
		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
422

423 424 425 426
	case file != "":
		if key, err = crypto.LoadECDSA(file); err != nil {
			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
		}
427

428 429 430 431 432 433 434 435
	case hex != "":
		if key, err = crypto.HexToECDSA(hex); err != nil {
			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
		}
	}
	return key
}

436 437 438 439 440 441 442 443
// MakeNodeName creates a node name from a base set and the command line flags.
func MakeNodeName(client, version string, ctx *cli.Context) string {
	name := common.MakeName(client, version)
	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
		name += "/" + identity
	}
	if ctx.GlobalBool(VMEnableJitFlag.Name) {
		name += "/JIT"
444
	}
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
	return name
}

// MakeBootstrapNodes creates a list of bootstrap nodes from the command line
// flags, reverting to pre-configured ones if none have been specified.
func MakeBootstrapNodes(ctx *cli.Context) []*discover.Node {
	// Return pre-configured nodes if none were manually requested
	if !ctx.GlobalIsSet(BootnodesFlag.Name) {
		if ctx.GlobalBool(TestNetFlag.Name) {
			return TestNetBootNodes
		}
		return FrontierBootNodes
	}
	// Otherwise parse and use the CLI bootstrap nodes
	bootnodes := []*discover.Node{}

	for _, url := range strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") {
		node, err := discover.ParseNode(url)
		if err != nil {
			glog.V(logger.Error).Infof("Bootstrap URL %s: %v\n", url, err)
			continue
		}
		bootnodes = append(bootnodes, node)
	}
	return bootnodes
}

// MakeListenAddress creates a TCP listening address string from set command
// line flags.
func MakeListenAddress(ctx *cli.Context) string {
	return fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
}

// MakeNAT creates a port mapper from set command line flags.
func MakeNAT(ctx *cli.Context) nat.Interface {
	natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
481
	if err != nil {
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
		Fatalf("Option %s: %v", NATFlag.Name, err)
	}
	return natif
}

// MakeGenesisBlock loads up a genesis block from an input file specified in the
// command line, or returns the empty string if none set.
func MakeGenesisBlock(ctx *cli.Context) string {
	genesis := ctx.GlobalString(GenesisFileFlag.Name)
	if genesis == "" {
		return ""
	}
	data, err := ioutil.ReadFile(genesis)
	if err != nil {
		Fatalf("Failed to load custom genesis file: %v", err)
	}
	return string(data)
}

// MakeAccountManager creates an account manager from set command line flags.
func MakeAccountManager(ctx *cli.Context) *accounts.Manager {
	// Create the keystore crypto primitive, light if requested
	scryptN := crypto.StandardScryptN
	scryptP := crypto.StandardScryptP

	if ctx.GlobalBool(LightKDFFlag.Name) {
		scryptN = crypto.LightScryptN
		scryptP = crypto.LightScryptP
	}
	// Assemble an account manager using the configured datadir
	var (
		datadir  = MustMakeDataDir(ctx)
		keystore = crypto.NewKeyStorePassphrase(filepath.Join(datadir, "keystore"), scryptN, scryptP)
	)
	return accounts.NewManager(keystore)
}

// MakeAddress converts an account specified directly as a hex encoded string or
// a key index in the key store to an internal account representation.
521
func MakeAddress(accman *accounts.Manager, account string) (a common.Address, err error) {
522 523
	// If the specified account is a valid address, return it
	if common.IsHexAddress(account) {
524
		return common.HexToAddress(account), nil
525 526 527 528
	}
	// Otherwise try to interpret the account as a keystore index
	index, err := strconv.Atoi(account)
	if err != nil {
529
		return a, fmt.Errorf("invalid account address or index %q", account)
530 531 532
	}
	hex, err := accman.AddressByIndex(index)
	if err != nil {
533
		return a, fmt.Errorf("can't get account #%d (%v)", index, err)
534
	}
535
	return common.HexToAddress(hex), nil
536 537 538 539 540 541
}

// MakeEtherbase retrieves the etherbase either from the directly specified
// command line flags or from the keystore if CLI indexed.
func MakeEtherbase(accman *accounts.Manager, ctx *cli.Context) common.Address {
	accounts, _ := accman.Accounts()
542
	if !ctx.GlobalIsSet(EtherbaseFlag.Name) && len(accounts) == 0 {
543
		glog.V(logger.Error).Infoln("WARNING: No etherbase set and no accounts found as default")
544 545
		return common.Address{}
	}
546 547 548
	etherbase := ctx.GlobalString(EtherbaseFlag.Name)
	if etherbase == "" {
		return common.Address{}
549
	}
550 551
	// If the specified etherbase is a valid address, return it
	addr, err := MakeAddress(accman, etherbase)
552
	if err != nil {
553
		Fatalf("Option %q: %v", EtherbaseFlag.Name, err)
554
	}
555
	return addr
556 557 558 559 560 561 562
}

// MakeMinerExtra resolves extradata for the miner from the set command line flags
// or returns a default one composed on the client, runtime and OS metadata.
func MakeMinerExtra(extra []byte, ctx *cli.Context) []byte {
	if ctx.GlobalIsSet(ExtraDataFlag.Name) {
		return []byte(ctx.GlobalString(ExtraDataFlag.Name))
563
	}
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
	return extra
}

// MakePasswordList loads up a list of password from a file specified by the
// command line flags.
func MakePasswordList(ctx *cli.Context) []string {
	if path := ctx.GlobalString(PasswordFileFlag.Name); path != "" {
		blob, err := ioutil.ReadFile(path)
		if err != nil {
			Fatalf("Failed to read password file: %v", err)
		}
		return strings.Split(string(blob), "\n")
	}
	return nil
}

// MakeSystemNode sets up a local node, configures the services to launch and
// assembles the P2P protocol stack.
func MakeSystemNode(name, version string, extra []byte, ctx *cli.Context) *node.Node {
	// Avoid conflicting network flags
	networks, netFlags := 0, []cli.BoolFlag{DevModeFlag, TestNetFlag, OlympicFlag}
	for _, flag := range netFlags {
		if ctx.GlobalBool(flag.Name) {
			networks++
		}
	}
	if networks > 1 {
		Fatalf("The %v flags are mutually exclusive", netFlags)
	}
	// Configure the node's service container
	stackConf := &node.Config{
		DataDir:         MustMakeDataDir(ctx),
		PrivateKey:      MakeNodeKey(ctx),
		Name:            MakeNodeName(name, version, ctx),
		NoDiscovery:     ctx.GlobalBool(NoDiscoverFlag.Name),
		BootstrapNodes:  MakeBootstrapNodes(ctx),
		ListenAddr:      MakeListenAddress(ctx),
		NAT:             MakeNAT(ctx),
		MaxPeers:        ctx.GlobalInt(MaxPeersFlag.Name),
		MaxPendingPeers: ctx.GlobalInt(MaxPendingPeersFlag.Name),
	}
	// Configure the Ethereum service
	accman := MakeAccountManager(ctx)

	ethConf := &eth.Config{
		Genesis:                 MakeGenesisBlock(ctx),
610
		FastSync:                ctx.GlobalBool(FastSyncFlag.Name),
Z
zsfelfoldi 已提交
611
		BlockChainVersion:       ctx.GlobalInt(BlockchainVersionFlag.Name),
612
		DatabaseCache:           ctx.GlobalInt(CacheFlag.Name),
Z
zsfelfoldi 已提交
613
		NetworkId:               ctx.GlobalInt(NetworkIdFlag.Name),
614 615
		AccountManager:          accman,
		Etherbase:               MakeEtherbase(accman, ctx),
Z
zsfelfoldi 已提交
616
		MinerThreads:            ctx.GlobalInt(MinerThreadsFlag.Name),
617
		ExtraData:               MakeMinerExtra(extra, ctx),
Z
zsfelfoldi 已提交
618
		NatSpec:                 ctx.GlobalBool(NatspecEnabledFlag.Name),
Z
zelig 已提交
619
		DocRoot:                 ctx.GlobalString(DocRootFlag.Name),
Z
zsfelfoldi 已提交
620 621 622 623 624 625 626 627 628
		GasPrice:                common.String2Big(ctx.GlobalString(GasPriceFlag.Name)),
		GpoMinGasPrice:          common.String2Big(ctx.GlobalString(GpoMinGasPriceFlag.Name)),
		GpoMaxGasPrice:          common.String2Big(ctx.GlobalString(GpoMaxGasPriceFlag.Name)),
		GpoFullBlockRatio:       ctx.GlobalInt(GpoFullBlockRatioFlag.Name),
		GpobaseStepDown:         ctx.GlobalInt(GpobaseStepDownFlag.Name),
		GpobaseStepUp:           ctx.GlobalInt(GpobaseStepUpFlag.Name),
		GpobaseCorrectionFactor: ctx.GlobalInt(GpobaseCorrectionFactorFlag.Name),
		SolcPath:                ctx.GlobalString(SolcPathFlag.Name),
		AutoDAG:                 ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name),
629
	}
630 631
	// Configure the Whisper service
	shhEnable := ctx.GlobalBool(WhisperEnabledFlag.Name)
632

633 634 635 636 637 638 639 640 641
	// Override any default configs in dev mode or the test net
	switch {
	case ctx.GlobalBool(OlympicFlag.Name):
		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
			ethConf.NetworkId = 1
		}
		if !ctx.GlobalIsSet(GenesisFileFlag.Name) {
			ethConf.Genesis = core.OlympicGenesisBlock()
		}
642

643 644 645 646 647 648 649 650
	case ctx.GlobalBool(TestNetFlag.Name):
		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
			ethConf.NetworkId = 2
		}
		if !ctx.GlobalIsSet(GenesisFileFlag.Name) {
			ethConf.Genesis = core.TestNetGenesisBlock()
		}
		state.StartingNonce = 1048576 // (2**20)
651

652 653 654 655
	case ctx.GlobalBool(DevModeFlag.Name):
		// Override the base network stack configs
		if !ctx.GlobalIsSet(DataDirFlag.Name) {
			stackConf.DataDir = filepath.Join(os.TempDir(), "/ethereum_dev_mode")
656 657
		}
		if !ctx.GlobalIsSet(MaxPeersFlag.Name) {
658
			stackConf.MaxPeers = 0
659 660
		}
		if !ctx.GlobalIsSet(ListenPortFlag.Name) {
661 662 663 664 665 666 667 668
			stackConf.ListenAddr = ":0"
		}
		// Override the Ethereum protocol configs
		if !ctx.GlobalIsSet(GenesisFileFlag.Name) {
			ethConf.Genesis = core.OlympicGenesisBlock()
		}
		if !ctx.GlobalIsSet(GasPriceFlag.Name) {
			ethConf.GasPrice = new(big.Int)
669 670
		}
		if !ctx.GlobalIsSet(WhisperEnabledFlag.Name) {
671
			shhEnable = true
672
		}
673 674
		if !ctx.GlobalIsSet(VMDebugFlag.Name) {
			vm.Debug = true
675
		}
676
		ethConf.PowTest = true
677
	}
678 679 680 681 682
	// Assemble and return the protocol stack
	stack, err := node.New(stackConf)
	if err != nil {
		Fatalf("Failed to create the protocol stack: %v", err)
	}
683
	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
684 685 686 687 688
		return eth.New(ctx, ethConf)
	}); err != nil {
		Fatalf("Failed to register the Ethereum service: %v", err)
	}
	if shhEnable {
689
		if err := stack.Register(func(*node.ServiceContext) (node.Service, error) { return whisper.New(), nil }); err != nil {
690 691 692 693
			Fatalf("Failed to register the Whisper service: %v", err)
		}
	}
	return stack
694 695
}

696 697 698 699 700
// SetupLogger configures glog from the logging-related command line flags.
func SetupLogger(ctx *cli.Context) {
	glog.SetV(ctx.GlobalInt(VerbosityFlag.Name))
	glog.CopyStandardLogTo("INFO")
	glog.SetToStderr(true)
701 702 703 704 705 706
	if ctx.GlobalIsSet(LogFileFlag.Name) {
		logger.New("", ctx.GlobalString(LogFileFlag.Name), ctx.GlobalInt(VerbosityFlag.Name))
	}
	if ctx.GlobalIsSet(VMDebugFlag.Name) {
		vm.Debug = ctx.GlobalBool(VMDebugFlag.Name)
	}
707
}
708

709 710 711 712 713 714 715 716 717 718 719 720 721 722
// SetupNetwork configures the system for either the main net or some test network.
func SetupNetwork(ctx *cli.Context) {
	switch {
	case ctx.GlobalBool(OlympicFlag.Name):
		params.DurationLimit = big.NewInt(8)
		params.GenesisGasLimit = big.NewInt(3141592)
		params.MinGasLimit = big.NewInt(125000)
		params.MaximumExtraDataSize = big.NewInt(1024)
		NetworkIdFlag.Value = 0
		core.BlockReward = big.NewInt(1.5e+18)
		core.ExpDiffPeriod = big.NewInt(math.MaxInt64)
	}
}

723 724
// SetupVM configured the VM package's global settings
func SetupVM(ctx *cli.Context) {
725
	vm.EnableJit = ctx.GlobalBool(VMEnableJitFlag.Name)
726 727 728 729
	vm.ForceJit = ctx.GlobalBool(VMForceJitFlag.Name)
	vm.SetJITCacheSize(ctx.GlobalInt(VMJitCacheFlag.Name))
}

730
// MakeChain creates a chain manager from set command line flags.
731
func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database) {
732
	datadir := MustMakeDataDir(ctx)
733 734
	cache := ctx.GlobalInt(CacheFlag.Name)

735
	var err error
736
	if chainDb, err = ethdb.NewLDBDatabase(filepath.Join(datadir, "chaindata"), cache); err != nil {
737 738
		Fatalf("Could not open database: %v", err)
	}
739
	if ctx.GlobalBool(OlympicFlag.Name) {
740
		_, err := core.WriteTestNetGenesisBlock(chainDb)
741 742 743 744
		if err != nil {
			glog.Fatalln(err)
		}
	}
745 746

	eventMux := new(event.TypeMux)
747
	pow := ethash.New()
748
	//genesis := core.GenesisBlock(uint64(ctx.GlobalInt(GenesisNonceFlag.Name)), blockDB)
749
	chain, err = core.NewBlockChain(chainDb, pow, eventMux)
O
obscuren 已提交
750 751 752 753
	if err != nil {
		Fatalf("Could not start chainmanager: %v", err)
	}

754
	return chain, chainDb
755
}
F
Felix Lange 已提交
756

B
Bas van Kervel 已提交
757
func IpcSocketPath(ctx *cli.Context) (ipcpath string) {
758
	if runtime.GOOS == "windows" {
B
Bas van Kervel 已提交
759
		ipcpath = common.DefaultIpcPath()
B
Bas van Kervel 已提交
760
		if ctx.GlobalIsSet(IPCPathFlag.Name) {
B
Bas van Kervel 已提交
761 762 763 764
			ipcpath = ctx.GlobalString(IPCPathFlag.Name)
		}
	} else {
		ipcpath = common.DefaultIpcPath()
B
Bas van Kervel 已提交
765
		if ctx.GlobalIsSet(DataDirFlag.Name) {
B
Bas van Kervel 已提交
766 767
			ipcpath = filepath.Join(ctx.GlobalString(DataDirFlag.Name), "geth.ipc")
		}
B
Bas van Kervel 已提交
768 769 770
		if ctx.GlobalIsSet(IPCPathFlag.Name) {
			ipcpath = ctx.GlobalString(IPCPathFlag.Name)
		}
B
Bas van Kervel 已提交
771 772 773 774 775
	}

	return
}

776 777
// StartIPC starts a IPC JSON-RPC API server.
func StartIPC(stack *node.Node, ctx *cli.Context) error {
B
Bas van Kervel 已提交
778
	config := comms.IpcConfig{
B
Bas van Kervel 已提交
779
		Endpoint: IpcSocketPath(ctx),
B
Bas van Kervel 已提交
780 781
	}

782
	initializer := func(conn net.Conn) (comms.Stopper, shared.EthereumApi, error) {
783 784 785 786 787
		var ethereum *eth.Ethereum
		if err := stack.Service(&ethereum); err != nil {
			return nil, nil, err
		}
		fe := useragent.NewRemoteFrontend(conn, ethereum.AccountManager())
788 789
		xeth := xeth.New(stack, fe)
		apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec.JSON, xeth, stack)
B
Bas van Kervel 已提交
790
		if err != nil {
791
			return nil, nil, err
B
Bas van Kervel 已提交
792
		}
793
		return xeth, api.Merge(apis...), nil
B
Bas van Kervel 已提交
794
	}
B
Bas van Kervel 已提交
795
	return comms.StartIpc(config, codec.JSON, initializer)
B
Bas van Kervel 已提交
796 797
}

798 799
// StartRPC starts a HTTP JSON-RPC API server.
func StartRPC(stack *node.Node, ctx *cli.Context) error {
800
	config := comms.HttpConfig{
T
Taylor Gerring 已提交
801 802 803
		ListenAddress: ctx.GlobalString(RPCListenAddrFlag.Name),
		ListenPort:    uint(ctx.GlobalInt(RPCPortFlag.Name)),
		CorsDomain:    ctx.GlobalString(RPCCORSDomainFlag.Name),
804
	}
T
Taylor Gerring 已提交
805

806
	xeth := xeth.New(stack, nil)
807 808
	codec := codec.JSON

809
	apis, err := api.ParseApiString(ctx.GlobalString(RpcApiFlag.Name), codec, xeth, stack)
810 811 812
	if err != nil {
		return err
	}
B
Bas van Kervel 已提交
813
	return comms.StartHttp(config, codec, api.Merge(apis...))
814
}
815 816 817 818 819 820 821

func StartPProf(ctx *cli.Context) {
	address := fmt.Sprintf("localhost:%d", ctx.GlobalInt(PProfPortFlag.Name))
	go func() {
		log.Println(http.ListenAndServe(address, nil))
	}()
}