flags.go 14.7 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"
25
	"github.com/ethereum/go-ethereum/rpc"
B
Bas van Kervel 已提交
26 27
	"github.com/ethereum/go-ethereum/rpc/api"
	"github.com/ethereum/go-ethereum/rpc/codec"
28 29
	"github.com/ethereum/go-ethereum/rpc/comms"
	"github.com/ethereum/go-ethereum/xeth"
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 57
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 已提交
58 59 60
// NewApp creates an app with sane defaults.
func NewApp(version, usage string) *cli.App {
	app := cli.NewApp()
61
	app.Name = filepath.Base(os.Args[0])
F
Felix Lange 已提交
62
	app.Author = ""
O
obscuren 已提交
63
	//app.Authors = nil
F
Felix Lange 已提交
64 65 66 67 68 69
	app.Email = ""
	app.Version = version
	app.Usage = usage
	return app
}

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

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

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

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

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

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

320 321
// MakeNodeKey creates a node key from set command line flags.
func MakeNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) {
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
	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
}

339
// MakeEthConfig creates ethereum options from set command line flags.
340
func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
341 342 343 344
	customName := ctx.GlobalString(IdentityFlag.Name)
	if len(customName) > 0 {
		clientID += "/" + customName
	}
345
	return &eth.Config{
Z
zsfelfoldi 已提交
346 347 348 349 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
		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),
379
	}
380 381
}

382 383 384 385 386 387 388
// 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))
}
389

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

	eventMux := new(event.TypeMux)
405
	pow := ethash.New()
O
obscuren 已提交
406 407 408 409 410 411
	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)
	}

412
	proc := core.NewBlockProcessor(stateDB, extraDB, pow, chain, eventMux)
413 414
	chain.SetProcessor(proc)
	return chain, blockDB, stateDB, extraDB
415
}
F
Felix Lange 已提交
416

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

B
Bas van Kervel 已提交
424 425 426 427 428 429 430 431 432 433 434
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) != "" &&
435
			ctx.GlobalString(DataDirFlag.Name) != common.DefaultDataDir() {
B
Bas van Kervel 已提交
436 437 438 439 440 441 442
			ipcpath = filepath.Join(ctx.GlobalString(DataDirFlag.Name), "geth.ipc")
		}
	}

	return
}

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

	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...)
}

459
func StartRPC(eth *eth.Ethereum, ctx *cli.Context) error {
T
Taylor Gerring 已提交
460 461 462 463
	config := rpc.RpcConfig{
		ListenAddress: ctx.GlobalString(RPCListenAddrFlag.Name),
		ListenPort:    uint(ctx.GlobalInt(RPCPortFlag.Name)),
		CorsDomain:    ctx.GlobalString(RPCCORSDomainFlag.Name),
464
	}
T
Taylor Gerring 已提交
465 466

	xeth := xeth.New(eth, nil)
467
	return rpc.Start(xeth, config)
468
}
469 470 471 472 473 474 475

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