flags.go 14.9 KB
Newer Older
1 2 3 4
package utils

import (
	"crypto/ecdsa"
5 6
	"fmt"
	"log"
7
	"math/big"
8
	"net/http"
9
	"os"
10
	"path/filepath"
11
	"runtime"
12

13
	"github.com/codegangsta/cli"
14
	"github.com/ethereum/ethash"
F
Felix Lange 已提交
15
	"github.com/ethereum/go-ethereum/accounts"
Z
zelig 已提交
16
	"github.com/ethereum/go-ethereum/common"
17 18 19 20 21 22
	"github.com/ethereum/go-ethereum/core"
	"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 已提交
23
	"github.com/ethereum/go-ethereum/logger/glog"
24
	"github.com/ethereum/go-ethereum/p2p/nat"
B
Bas van Kervel 已提交
25 26
	"github.com/ethereum/go-ethereum/rpc/api"
	"github.com/ethereum/go-ethereum/rpc/codec"
27 28
	"github.com/ethereum/go-ethereum/rpc/comms"
	"github.com/ethereum/go-ethereum/xeth"
29 30
)

31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
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 已提交
57 58 59
// NewApp creates an app with sane defaults.
func NewApp(version, usage string) *cli.App {
	app := cli.NewApp()
60
	app.Name = filepath.Base(os.Args[0])
F
Felix Lange 已提交
61
	app.Author = ""
O
obscuren 已提交
62
	//app.Authors = nil
F
Felix Lange 已提交
63 64 65 66 67 68
	app.Email = ""
	app.Version = version
	app.Usage = usage
	return app
}

69 70 71 72 73 74 75 76 77
// 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
78
	DataDirFlag = DirectoryFlag{
79 80
		Name:  "datadir",
		Usage: "Data directory to be used",
81
		Value: DirectoryString{common.DefaultDataDir()},
82
	}
Z
zelig 已提交
83 84
	ProtocolVersionFlag = cli.IntFlag{
		Name:  "protocolversion",
85
		Usage: "ETH protocol version (integer)",
Z
zelig 已提交
86 87 88 89
		Value: eth.ProtocolVersion,
	}
	NetworkIdFlag = cli.IntFlag{
		Name:  "networkid",
90
		Usage: "Network Id (integer)",
Z
zelig 已提交
91 92
		Value: eth.NetworkId,
	}
93 94
	BlockchainVersionFlag = cli.IntFlag{
		Name:  "blockchainversion",
95
		Usage: "Blockchain version (integer)",
96 97
		Value: core.BlockChainVersion,
	}
O
obscuren 已提交
98 99 100 101 102
	GenesisNonceFlag = cli.IntFlag{
		Name:  "genesisnonce",
		Usage: "Sets the genesis nonce",
		Value: 42,
	}
103 104
	IdentityFlag = cli.StringFlag{
		Name:  "identity",
105
		Usage: "Custom node name",
106
	}
107 108 109 110
	NatspecEnabledFlag = cli.BoolFlag{
		Name:  "natspec",
		Usage: "Enable NatSpec confirmation notice",
	}
Z
zelig 已提交
111 112

	// miner settings
113 114 115 116 117 118 119 120 121
	MinerThreadsFlag = cli.IntFlag{
		Name:  "minerthreads",
		Usage: "Number of miner threads",
		Value: runtime.NumCPU(),
	}
	MiningEnabledFlag = cli.BoolFlag{
		Name:  "mine",
		Usage: "Enable mining",
	}
122 123 124 125
	AutoDAGFlag = cli.BoolFlag{
		Name:  "autodag",
		Usage: "Enable automatic DAG pregeneration",
	}
Z
zelig 已提交
126
	EtherbaseFlag = cli.StringFlag{
O
obscuren 已提交
127
		Name:  "etherbase",
128
		Usage: "Public address for block mining rewards. By default the address of your primary account is used",
Z
zelig 已提交
129 130
		Value: "primary",
	}
131 132 133
	GasPriceFlag = cli.StringFlag{
		Name:  "gasprice",
		Usage: "Sets the minimal gasprice when mining transactions",
134
		Value: new(big.Int).Mul(big.NewInt(1), common.Szabo).String(),
135
	}
Z
zelig 已提交
136 137 138

	UnlockedAccountFlag = cli.StringFlag{
		Name:  "unlock",
139
		Usage: "Unlock the account given until this program exits (prompts for password). '--unlock primary' unlocks the primary account",
Z
zelig 已提交
140 141 142 143
		Value: "",
	}
	PasswordFileFlag = cli.StringFlag{
		Name:  "password",
144
		Usage: "Path to password file to use with options and subcommands needing a password",
Z
zelig 已提交
145
		Value: "",
Z
zelig 已提交
146
	}
147

Z
zelig 已提交
148
	// logging and debug settings
149 150 151 152
	LogFileFlag = cli.StringFlag{
		Name:  "logfile",
		Usage: "Send log output to a file",
	}
153 154
	VerbosityFlag = cli.IntFlag{
		Name:  "verbosity",
155
		Usage: "Logging verbosity: 0-6 (0=silent, 1=error, 2=warn, 3=info, 4=core, 5=debug, 6=debug detail)",
156 157
		Value: int(logger.InfoLevel),
	}
158 159 160 161
	LogJSONFlag = cli.StringFlag{
		Name:  "logjson",
		Usage: "Send json structured log output to a file or '-' for standard output (default: no json output)",
		Value: "",
162
	}
163 164 165 166 167 168
	LogToStdErrFlag = cli.BoolFlag{
		Name:  "logtostderr",
		Usage: "Logs are written to standard error instead of to files.",
	}
	LogVModuleFlag = cli.GenericFlag{
		Name:  "vmodule",
169
		Usage: "The syntax of the argument is a comma-separated list of pattern=N, where pattern is a literal file name (minus the \".go\" suffix) or \"glob\" pattern and N is a log verbosity level.",
170 171
		Value: glog.GetVModule(),
	}
Z
zelig 已提交
172 173 174 175
	VMDebugFlag = cli.BoolFlag{
		Name:  "vmdebug",
		Usage: "Virtual Machine debug output",
	}
176 177
	BacktraceAtFlag = cli.GenericFlag{
		Name:  "backtrace_at",
178
		Usage: "If set to a file and line number (e.g., \"block.go:271\") holding a logging statement, a stack trace will be logged",
179 180
		Value: glog.GetTraceLocation(),
	}
181 182
	PProfEanbledFlag = cli.BoolFlag{
		Name:  "pprof",
183
		Usage: "Enable the profiling server on localhost",
184 185 186 187 188 189
	}
	PProfPortFlag = cli.IntFlag{
		Name:  "pprofport",
		Usage: "Port on which the profiler should listen",
		Value: 6060,
	}
190 191 192 193

	// RPC settings
	RPCEnabledFlag = cli.BoolFlag{
		Name:  "rpc",
194
		Usage: "Enable the JSON-RPC server",
195 196 197 198 199 200 201 202 203 204 205
	}
	RPCListenAddrFlag = cli.StringFlag{
		Name:  "rpcaddr",
		Usage: "Listening address for the JSON-RPC server",
		Value: "127.0.0.1",
	}
	RPCPortFlag = cli.IntFlag{
		Name:  "rpcport",
		Usage: "Port on which the JSON-RPC server should listen",
		Value: 8545,
	}
206 207 208 209 210
	RPCCORSDomainFlag = cli.StringFlag{
		Name:  "rpccorsdomain",
		Usage: "Domain on which to send Access-Control-Allow-Origin header",
		Value: "",
	}
211 212 213
	RpcApiFlag = cli.StringFlag{
		Name:  "rpcapi",
		Usage: "Specify the API's which are offered over the HTTP RPC interface",
214
		Value: comms.DefaultHttpRpcApis,
215
	}
B
Bas van Kervel 已提交
216 217 218 219 220 221
	IPCDisabledFlag = cli.BoolFlag{
		Name:  "ipcdisable",
		Usage: "Disable the IPC-RPC server",
	}
	IPCApiFlag = cli.StringFlag{
		Name:  "ipcapi",
222
		Usage: "Specify the API's which are offered over the IPC interface",
223
		Value: comms.DefaultIpcApis,
B
Bas van Kervel 已提交
224 225 226 227 228 229
	}
	IPCPathFlag = DirectoryFlag{
		Name:  "ipcpath",
		Usage: "Filename for IPC socket/pipe",
		Value: DirectoryString{common.DefaultIpcPath()},
	}
230 231 232
	// Network Settings
	MaxPeersFlag = cli.IntFlag{
		Name:  "maxpeers",
233
		Usage: "Maximum number of network peers (network disabled if set to 0)",
234
		Value: 25,
235
	}
236 237 238 239 240
	MaxPendingPeersFlag = cli.IntFlag{
		Name:  "maxpendpeers",
		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
		Value: 0,
	}
241 242 243 244 245 246 247
	ListenPortFlag = cli.IntFlag{
		Name:  "port",
		Usage: "Network listening port",
		Value: 30303,
	}
	BootnodesFlag = cli.StringFlag{
		Name:  "bootnodes",
248
		Usage: "Space-separated enode URLs for p2p discovery bootstrap",
249 250 251 252 253 254 255 256 257 258 259 260
		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",
261
		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
262 263
		Value: "any",
	}
264 265 266 267
	NoDiscoverFlag = cli.BoolFlag{
		Name:  "nodiscover",
		Usage: "Disables the peer discovery mechanism (manual peer addition)",
	}
268 269
	WhisperEnabledFlag = cli.BoolFlag{
		Name:  "shh",
270
		Usage: "Enable whisper",
271
	}
272
	// ATM the url is left to the user and deployment to
Z
CLI:  
zelig 已提交
273 274 275 276 277
	JSpathFlag = cli.StringFlag{
		Name:  "jspath",
		Usage: "JS library path to be used with console and js subcommands",
		Value: ".",
	}
278 279 280 281 282
	SolcPathFlag = cli.StringFlag{
		Name:  "solc",
		Usage: "solidity compiler to be used",
		Value: "solc",
	}
Z
zsfelfoldi 已提交
283 284 285
	GpoMinGasPriceFlag = cli.StringFlag{
		Name:  "gpomin",
		Usage: "Minimum suggested gas price",
286
		Value: new(big.Int).Mul(big.NewInt(1), common.Szabo).String(),
Z
zsfelfoldi 已提交
287 288 289 290
	}
	GpoMaxGasPriceFlag = cli.StringFlag{
		Name:  "gpomax",
		Usage: "Maximum suggested gas price",
291
		Value: new(big.Int).Mul(big.NewInt(100), common.Szabo).String(),
Z
zsfelfoldi 已提交
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
	}
	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,
	}
313 314
)

315 316
// MakeNAT creates a port mapper from set command line flags.
func MakeNAT(ctx *cli.Context) nat.Interface {
317 318 319 320 321 322 323
	natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
	if err != nil {
		Fatalf("Option %s: %v", NATFlag.Name, err)
	}
	return natif
}

324 325
// MakeNodeKey creates a node key from set command line flags.
func MakeNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) {
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
	hex, file := ctx.GlobalString(NodeKeyHexFlag.Name), ctx.GlobalString(NodeKeyFileFlag.Name)
	var err error
	switch {
	case file != "" && hex != "":
		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
	case file != "":
		if key, err = crypto.LoadECDSA(file); err != nil {
			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
		}
	case hex != "":
		if key, err = crypto.HexToECDSA(hex); err != nil {
			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
		}
	}
	return key
}

343
// MakeEthConfig creates ethereum options from set command line flags.
344
func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
345 346 347 348
	customName := ctx.GlobalString(IdentityFlag.Name)
	if len(customName) > 0 {
		clientID += "/" + customName
	}
349
	return &eth.Config{
Z
zsfelfoldi 已提交
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
		Name:                    common.MakeName(clientID, version),
		DataDir:                 ctx.GlobalString(DataDirFlag.Name),
		ProtocolVersion:         ctx.GlobalInt(ProtocolVersionFlag.Name),
		GenesisNonce:            ctx.GlobalInt(GenesisNonceFlag.Name),
		BlockChainVersion:       ctx.GlobalInt(BlockchainVersionFlag.Name),
		SkipBcVersionCheck:      false,
		NetworkId:               ctx.GlobalInt(NetworkIdFlag.Name),
		LogFile:                 ctx.GlobalString(LogFileFlag.Name),
		Verbosity:               ctx.GlobalInt(VerbosityFlag.Name),
		LogJSON:                 ctx.GlobalString(LogJSONFlag.Name),
		Etherbase:               ctx.GlobalString(EtherbaseFlag.Name),
		MinerThreads:            ctx.GlobalInt(MinerThreadsFlag.Name),
		AccountManager:          MakeAccountManager(ctx),
		VmDebug:                 ctx.GlobalBool(VMDebugFlag.Name),
		MaxPeers:                ctx.GlobalInt(MaxPeersFlag.Name),
		MaxPendingPeers:         ctx.GlobalInt(MaxPendingPeersFlag.Name),
		Port:                    ctx.GlobalString(ListenPortFlag.Name),
		NAT:                     MakeNAT(ctx),
		NatSpec:                 ctx.GlobalBool(NatspecEnabledFlag.Name),
		Discovery:               !ctx.GlobalBool(NoDiscoverFlag.Name),
		NodeKey:                 MakeNodeKey(ctx),
		Shh:                     ctx.GlobalBool(WhisperEnabledFlag.Name),
		Dial:                    true,
		BootNodes:               ctx.GlobalString(BootnodesFlag.Name),
		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),
383
	}
384 385
}

386 387 388 389 390 391 392
// 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)
	glog.SetLogDir(ctx.GlobalString(LogFileFlag.Name))
}
393

394 395
// MakeChain creates a chain manager from set command line flags.
func MakeChain(ctx *cli.Context) (chain *core.ChainManager, blockDB, stateDB, extraDB common.Database) {
396 397 398
	dd := ctx.GlobalString(DataDirFlag.Name)
	var err error
	if blockDB, err = ethdb.NewLDBDatabase(filepath.Join(dd, "blockchain")); err != nil {
399 400
		Fatalf("Could not open database: %v", err)
	}
401
	if stateDB, err = ethdb.NewLDBDatabase(filepath.Join(dd, "state")); err != nil {
402 403
		Fatalf("Could not open database: %v", err)
	}
404
	if extraDB, err = ethdb.NewLDBDatabase(filepath.Join(dd, "extra")); err != nil {
405 406 407 408
		Fatalf("Could not open database: %v", err)
	}

	eventMux := new(event.TypeMux)
409
	pow := ethash.New()
O
obscuren 已提交
410 411 412 413 414 415
	genesis := core.GenesisBlock(uint64(ctx.GlobalInt(GenesisNonceFlag.Name)), blockDB)
	chain, err = core.NewChainManager(genesis, blockDB, stateDB, pow, eventMux)
	if err != nil {
		Fatalf("Could not start chainmanager: %v", err)
	}

416
	proc := core.NewBlockProcessor(stateDB, extraDB, pow, chain, eventMux)
417 418
	chain.SetProcessor(proc)
	return chain, blockDB, stateDB, extraDB
419
}
F
Felix Lange 已提交
420

421 422
// MakeChain creates an account manager from set command line flags.
func MakeAccountManager(ctx *cli.Context) *accounts.Manager {
F
Felix Lange 已提交
423
	dataDir := ctx.GlobalString(DataDirFlag.Name)
G
Gustav Simonsson 已提交
424
	ks := crypto.NewKeyStorePassphrase(filepath.Join(dataDir, "keystore"))
425
	return accounts.NewManager(ks)
F
Felix Lange 已提交
426
}
427

B
Bas van Kervel 已提交
428 429 430 431 432 433 434 435 436 437 438
func IpcSocketPath(ctx *cli.Context) (ipcpath string) {
	if common.IsWindows() {
		ipcpath = common.DefaultIpcPath()
		if ipcpath != ctx.GlobalString(IPCPathFlag.Name) {
			ipcpath = ctx.GlobalString(IPCPathFlag.Name)
		}
	} else {
		ipcpath = common.DefaultIpcPath()
		if ctx.GlobalString(IPCPathFlag.Name) != common.DefaultIpcPath() {
			ipcpath = ctx.GlobalString(IPCPathFlag.Name)
		} else if ctx.GlobalString(DataDirFlag.Name) != "" &&
439
			ctx.GlobalString(DataDirFlag.Name) != common.DefaultDataDir() {
B
Bas van Kervel 已提交
440 441 442 443 444 445 446
			ipcpath = filepath.Join(ctx.GlobalString(DataDirFlag.Name), "geth.ipc")
		}
	}

	return
}

B
Bas van Kervel 已提交
447 448
func StartIPC(eth *eth.Ethereum, ctx *cli.Context) error {
	config := comms.IpcConfig{
B
Bas van Kervel 已提交
449
		Endpoint: IpcSocketPath(ctx),
B
Bas van Kervel 已提交
450 451 452 453 454 455 456 457 458 459 460 461 462
	}

	xeth := xeth.New(eth, nil)
	codec := codec.JSON

	apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec, xeth, eth)
	if err != nil {
		return err
	}

	return comms.StartIpc(config, codec, apis...)
}

463
func StartRPC(eth *eth.Ethereum, ctx *cli.Context) error {
464
	config := comms.HttpConfig{
T
Taylor Gerring 已提交
465 466 467
		ListenAddress: ctx.GlobalString(RPCListenAddrFlag.Name),
		ListenPort:    uint(ctx.GlobalInt(RPCPortFlag.Name)),
		CorsDomain:    ctx.GlobalString(RPCCORSDomainFlag.Name),
468
	}
T
Taylor Gerring 已提交
469 470

	xeth := xeth.New(eth, nil)
471 472 473 474 475 476 477 478
	codec := codec.JSON

	apis, err := api.ParseApiString(ctx.GlobalString(RpcApiFlag.Name), codec, xeth, eth)
	if err != nil {
		return err
	}

	return comms.StartHttp(config, codec, apis...)
479
}
480 481 482 483 484 485 486

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