github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/cmd/utils/flags.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // 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/>. 16 17 package utils 18 19 import ( 20 "crypto/ecdsa" 21 "fmt" 22 "log" 23 "math/big" 24 "net" 25 "net/http" 26 "os" 27 "path/filepath" 28 "runtime" 29 "strconv" 30 31 "github.com/codegangsta/cli" 32 "github.com/ethereum/ethash" 33 "github.com/ethereum/go-ethereum/accounts" 34 "github.com/ethereum/go-ethereum/common" 35 "github.com/ethereum/go-ethereum/core" 36 "github.com/ethereum/go-ethereum/core/vm" 37 "github.com/ethereum/go-ethereum/crypto" 38 "github.com/ethereum/go-ethereum/eth" 39 "github.com/ethereum/go-ethereum/ethdb" 40 "github.com/ethereum/go-ethereum/event" 41 "github.com/ethereum/go-ethereum/logger" 42 "github.com/ethereum/go-ethereum/logger/glog" 43 "github.com/ethereum/go-ethereum/metrics" 44 "github.com/ethereum/go-ethereum/p2p/nat" 45 "github.com/ethereum/go-ethereum/rpc/api" 46 "github.com/ethereum/go-ethereum/rpc/codec" 47 "github.com/ethereum/go-ethereum/rpc/comms" 48 "github.com/ethereum/go-ethereum/rpc/shared" 49 "github.com/ethereum/go-ethereum/rpc/useragent" 50 "github.com/ethereum/go-ethereum/xeth" 51 ) 52 53 func init() { 54 cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] 55 56 VERSION: 57 {{.Version}} 58 59 COMMANDS: 60 {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 61 {{end}}{{if .Flags}} 62 GLOBAL OPTIONS: 63 {{range .Flags}}{{.}} 64 {{end}}{{end}} 65 ` 66 67 cli.CommandHelpTemplate = `{{.Name}}{{if .Subcommands}} command{{end}}{{if .Flags}} [command options]{{end}} [arguments...] 68 {{if .Description}}{{.Description}} 69 {{end}}{{if .Subcommands}} 70 SUBCOMMANDS: 71 {{range .Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 72 {{end}}{{end}}{{if .Flags}} 73 OPTIONS: 74 {{range .Flags}}{{.}} 75 {{end}}{{end}} 76 ` 77 } 78 79 // NewApp creates an app with sane defaults. 80 func NewApp(version, usage string) *cli.App { 81 app := cli.NewApp() 82 app.Name = filepath.Base(os.Args[0]) 83 app.Author = "" 84 //app.Authors = nil 85 app.Email = "" 86 app.Version = version 87 app.Usage = usage 88 return app 89 } 90 91 // These are all the command line flags we support. 92 // If you add to this list, please remember to include the 93 // flag in the appropriate command definition. 94 // 95 // The flags are defined here so their names and help texts 96 // are the same for all commands. 97 98 var ( 99 // General settings 100 DataDirFlag = DirectoryFlag{ 101 Name: "datadir", 102 Usage: "Data directory to be used", 103 Value: DirectoryString{common.DefaultDataDir()}, 104 } 105 NetworkIdFlag = cli.IntFlag{ 106 Name: "networkid", 107 Usage: "Network Id (integer)", 108 Value: eth.NetworkId, 109 } 110 BlockchainVersionFlag = cli.IntFlag{ 111 Name: "blockchainversion", 112 Usage: "Blockchain version (integer)", 113 Value: core.BlockChainVersion, 114 } 115 GenesisNonceFlag = cli.IntFlag{ 116 Name: "genesisnonce", 117 Usage: "Sets the genesis nonce", 118 Value: 42, 119 } 120 GenesisFileFlag = cli.StringFlag{ 121 Name: "genesis", 122 Usage: "Inserts/Overwrites the genesis block (json format)", 123 } 124 IdentityFlag = cli.StringFlag{ 125 Name: "identity", 126 Usage: "Custom node name", 127 } 128 NatspecEnabledFlag = cli.BoolFlag{ 129 Name: "natspec", 130 Usage: "Enable NatSpec confirmation notice", 131 } 132 CacheFlag = cli.IntFlag{ 133 Name: "cache", 134 Usage: "Megabytes of memory allocated to internal caching", 135 Value: 0, 136 } 137 OlympicFlag = cli.BoolFlag{ 138 Name: "olympic", 139 Usage: "Use olympic style protocol", 140 } 141 142 // miner settings 143 MinerThreadsFlag = cli.IntFlag{ 144 Name: "minerthreads", 145 Usage: "Number of miner threads", 146 Value: runtime.NumCPU(), 147 } 148 MiningEnabledFlag = cli.BoolFlag{ 149 Name: "mine", 150 Usage: "Enable mining", 151 } 152 AutoDAGFlag = cli.BoolFlag{ 153 Name: "autodag", 154 Usage: "Enable automatic DAG pregeneration", 155 } 156 EtherbaseFlag = cli.StringFlag{ 157 Name: "etherbase", 158 Usage: "Public address for block mining rewards. By default the address first created is used", 159 Value: "0", 160 } 161 GasPriceFlag = cli.StringFlag{ 162 Name: "gasprice", 163 Usage: "Sets the minimal gasprice when mining transactions", 164 Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(), 165 } 166 167 UnlockedAccountFlag = cli.StringFlag{ 168 Name: "unlock", 169 Usage: "Unlock the account given until this program exits (prompts for password). '--unlock n' unlocks the n-th account in order or creation.", 170 Value: "", 171 } 172 PasswordFileFlag = cli.StringFlag{ 173 Name: "password", 174 Usage: "Path to password file to use with options and subcommands needing a password", 175 Value: "", 176 } 177 178 // vm flags 179 VMDebugFlag = cli.BoolFlag{ 180 Name: "vmdebug", 181 Usage: "Virtual Machine debug output", 182 } 183 VMForceJitFlag = cli.BoolFlag{ 184 Name: "forcejit", 185 Usage: "Force the JIT VM to take precedence", 186 } 187 VMJitCacheFlag = cli.IntFlag{ 188 Name: "jitcache", 189 Usage: "Amount of cached JIT VM programs", 190 Value: 64, 191 } 192 VMEnableJitFlag = cli.BoolFlag{ 193 Name: "jitvm", 194 Usage: "Enable the JIT VM", 195 } 196 197 // logging and debug settings 198 LogFileFlag = cli.StringFlag{ 199 Name: "logfile", 200 Usage: "Send log output to a file", 201 } 202 VerbosityFlag = cli.IntFlag{ 203 Name: "verbosity", 204 Usage: "Logging verbosity: 0-6 (0=silent, 1=error, 2=warn, 3=info, 4=core, 5=debug, 6=debug detail)", 205 Value: int(logger.InfoLevel), 206 } 207 LogJSONFlag = cli.StringFlag{ 208 Name: "logjson", 209 Usage: "Send json structured log output to a file or '-' for standard output (default: no json output)", 210 Value: "", 211 } 212 LogToStdErrFlag = cli.BoolFlag{ 213 Name: "logtostderr", 214 Usage: "Logs are written to standard error instead of to files.", 215 } 216 LogVModuleFlag = cli.GenericFlag{ 217 Name: "vmodule", 218 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.", 219 Value: glog.GetVModule(), 220 } 221 BacktraceAtFlag = cli.GenericFlag{ 222 Name: "backtrace_at", 223 Usage: "If set to a file and line number (e.g., \"block.go:271\") holding a logging statement, a stack trace will be logged", 224 Value: glog.GetTraceLocation(), 225 } 226 PProfEanbledFlag = cli.BoolFlag{ 227 Name: "pprof", 228 Usage: "Enable the profiling server on localhost", 229 } 230 PProfPortFlag = cli.IntFlag{ 231 Name: "pprofport", 232 Usage: "Port on which the profiler should listen", 233 Value: 6060, 234 } 235 MetricsEnabledFlag = cli.BoolFlag{ 236 Name: metrics.MetricsEnabledFlag, 237 Usage: "Enables metrics collection and reporting", 238 } 239 240 // RPC settings 241 RPCEnabledFlag = cli.BoolFlag{ 242 Name: "rpc", 243 Usage: "Enable the JSON-RPC server", 244 } 245 RPCListenAddrFlag = cli.StringFlag{ 246 Name: "rpcaddr", 247 Usage: "Listening address for the JSON-RPC server", 248 Value: "127.0.0.1", 249 } 250 RPCPortFlag = cli.IntFlag{ 251 Name: "rpcport", 252 Usage: "Port on which the JSON-RPC server should listen", 253 Value: 8545, 254 } 255 RPCCORSDomainFlag = cli.StringFlag{ 256 Name: "rpccorsdomain", 257 Usage: "Domain on which to send Access-Control-Allow-Origin header", 258 Value: "", 259 } 260 RpcApiFlag = cli.StringFlag{ 261 Name: "rpcapi", 262 Usage: "Specify the API's which are offered over the HTTP RPC interface", 263 Value: comms.DefaultHttpRpcApis, 264 } 265 IPCDisabledFlag = cli.BoolFlag{ 266 Name: "ipcdisable", 267 Usage: "Disable the IPC-RPC server", 268 } 269 IPCApiFlag = cli.StringFlag{ 270 Name: "ipcapi", 271 Usage: "Specify the API's which are offered over the IPC interface", 272 Value: comms.DefaultIpcApis, 273 } 274 IPCPathFlag = DirectoryFlag{ 275 Name: "ipcpath", 276 Usage: "Filename for IPC socket/pipe", 277 Value: DirectoryString{common.DefaultIpcPath()}, 278 } 279 ExecFlag = cli.StringFlag{ 280 Name: "exec", 281 Usage: "Execute javascript statement (only in combination with console/attach)", 282 } 283 // Network Settings 284 MaxPeersFlag = cli.IntFlag{ 285 Name: "maxpeers", 286 Usage: "Maximum number of network peers (network disabled if set to 0)", 287 Value: 25, 288 } 289 MaxPendingPeersFlag = cli.IntFlag{ 290 Name: "maxpendpeers", 291 Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", 292 Value: 0, 293 } 294 ListenPortFlag = cli.IntFlag{ 295 Name: "port", 296 Usage: "Network listening port", 297 Value: 30303, 298 } 299 BootnodesFlag = cli.StringFlag{ 300 Name: "bootnodes", 301 Usage: "Space-separated enode URLs for p2p discovery bootstrap", 302 Value: "", 303 } 304 NodeKeyFileFlag = cli.StringFlag{ 305 Name: "nodekey", 306 Usage: "P2P node key file", 307 } 308 NodeKeyHexFlag = cli.StringFlag{ 309 Name: "nodekeyhex", 310 Usage: "P2P node key as hex (for testing)", 311 } 312 NATFlag = cli.StringFlag{ 313 Name: "nat", 314 Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)", 315 Value: "any", 316 } 317 NoDiscoverFlag = cli.BoolFlag{ 318 Name: "nodiscover", 319 Usage: "Disables the peer discovery mechanism (manual peer addition)", 320 } 321 WhisperEnabledFlag = cli.BoolFlag{ 322 Name: "shh", 323 Usage: "Enable whisper", 324 } 325 // ATM the url is left to the user and deployment to 326 JSpathFlag = cli.StringFlag{ 327 Name: "jspath", 328 Usage: "JS library path to be used with console and js subcommands", 329 Value: ".", 330 } 331 SolcPathFlag = cli.StringFlag{ 332 Name: "solc", 333 Usage: "solidity compiler to be used", 334 Value: "solc", 335 } 336 GpoMinGasPriceFlag = cli.StringFlag{ 337 Name: "gpomin", 338 Usage: "Minimum suggested gas price", 339 Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(), 340 } 341 GpoMaxGasPriceFlag = cli.StringFlag{ 342 Name: "gpomax", 343 Usage: "Maximum suggested gas price", 344 Value: new(big.Int).Mul(big.NewInt(500), common.Shannon).String(), 345 } 346 GpoFullBlockRatioFlag = cli.IntFlag{ 347 Name: "gpofull", 348 Usage: "Full block threshold for gas price calculation (%)", 349 Value: 80, 350 } 351 GpobaseStepDownFlag = cli.IntFlag{ 352 Name: "gpobasedown", 353 Usage: "Suggested gas price base step down ratio (1/1000)", 354 Value: 10, 355 } 356 GpobaseStepUpFlag = cli.IntFlag{ 357 Name: "gpobaseup", 358 Usage: "Suggested gas price base step up ratio (1/1000)", 359 Value: 100, 360 } 361 GpobaseCorrectionFactorFlag = cli.IntFlag{ 362 Name: "gpobasecf", 363 Usage: "Suggested gas price base correction factor (%)", 364 Value: 110, 365 } 366 ) 367 368 // MakeNAT creates a port mapper from set command line flags. 369 func MakeNAT(ctx *cli.Context) nat.Interface { 370 natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name)) 371 if err != nil { 372 Fatalf("Option %s: %v", NATFlag.Name, err) 373 } 374 return natif 375 } 376 377 // MakeNodeKey creates a node key from set command line flags. 378 func MakeNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) { 379 hex, file := ctx.GlobalString(NodeKeyHexFlag.Name), ctx.GlobalString(NodeKeyFileFlag.Name) 380 var err error 381 switch { 382 case file != "" && hex != "": 383 Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) 384 case file != "": 385 if key, err = crypto.LoadECDSA(file); err != nil { 386 Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) 387 } 388 case hex != "": 389 if key, err = crypto.HexToECDSA(hex); err != nil { 390 Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) 391 } 392 } 393 return key 394 } 395 396 // MakeEthConfig creates ethereum options from set command line flags. 397 func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { 398 customName := ctx.GlobalString(IdentityFlag.Name) 399 if len(customName) > 0 { 400 clientID += "/" + customName 401 } 402 am := MakeAccountManager(ctx) 403 etherbase, err := ParamToAddress(ctx.GlobalString(EtherbaseFlag.Name), am) 404 if err != nil { 405 glog.V(logger.Error).Infoln("WARNING: No etherbase set and no accounts found as default") 406 } 407 408 return ð.Config{ 409 Name: common.MakeName(clientID, version), 410 DataDir: ctx.GlobalString(DataDirFlag.Name), 411 GenesisNonce: ctx.GlobalInt(GenesisNonceFlag.Name), 412 GenesisFile: ctx.GlobalString(GenesisFileFlag.Name), 413 BlockChainVersion: ctx.GlobalInt(BlockchainVersionFlag.Name), 414 DatabaseCache: ctx.GlobalInt(CacheFlag.Name), 415 SkipBcVersionCheck: false, 416 NetworkId: ctx.GlobalInt(NetworkIdFlag.Name), 417 LogFile: ctx.GlobalString(LogFileFlag.Name), 418 Verbosity: ctx.GlobalInt(VerbosityFlag.Name), 419 LogJSON: ctx.GlobalString(LogJSONFlag.Name), 420 Etherbase: common.HexToAddress(etherbase), 421 MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name), 422 AccountManager: am, 423 VmDebug: ctx.GlobalBool(VMDebugFlag.Name), 424 MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name), 425 MaxPendingPeers: ctx.GlobalInt(MaxPendingPeersFlag.Name), 426 Port: ctx.GlobalString(ListenPortFlag.Name), 427 Olympic: ctx.GlobalBool(OlympicFlag.Name), 428 NAT: MakeNAT(ctx), 429 NatSpec: ctx.GlobalBool(NatspecEnabledFlag.Name), 430 Discovery: !ctx.GlobalBool(NoDiscoverFlag.Name), 431 NodeKey: MakeNodeKey(ctx), 432 Shh: ctx.GlobalBool(WhisperEnabledFlag.Name), 433 Dial: true, 434 BootNodes: ctx.GlobalString(BootnodesFlag.Name), 435 GasPrice: common.String2Big(ctx.GlobalString(GasPriceFlag.Name)), 436 GpoMinGasPrice: common.String2Big(ctx.GlobalString(GpoMinGasPriceFlag.Name)), 437 GpoMaxGasPrice: common.String2Big(ctx.GlobalString(GpoMaxGasPriceFlag.Name)), 438 GpoFullBlockRatio: ctx.GlobalInt(GpoFullBlockRatioFlag.Name), 439 GpobaseStepDown: ctx.GlobalInt(GpobaseStepDownFlag.Name), 440 GpobaseStepUp: ctx.GlobalInt(GpobaseStepUpFlag.Name), 441 GpobaseCorrectionFactor: ctx.GlobalInt(GpobaseCorrectionFactorFlag.Name), 442 SolcPath: ctx.GlobalString(SolcPathFlag.Name), 443 AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name), 444 } 445 } 446 447 // SetupLogger configures glog from the logging-related command line flags. 448 func SetupLogger(ctx *cli.Context) { 449 glog.SetV(ctx.GlobalInt(VerbosityFlag.Name)) 450 glog.CopyStandardLogTo("INFO") 451 glog.SetToStderr(true) 452 glog.SetLogDir(ctx.GlobalString(LogFileFlag.Name)) 453 } 454 455 // SetupVM configured the VM package's global settings 456 func SetupVM(ctx *cli.Context) { 457 vm.EnableJit = ctx.GlobalBool(VMEnableJitFlag.Name) 458 vm.ForceJit = ctx.GlobalBool(VMForceJitFlag.Name) 459 vm.SetJITCacheSize(ctx.GlobalInt(VMJitCacheFlag.Name)) 460 } 461 462 // MakeChain creates a chain manager from set command line flags. 463 func MakeChain(ctx *cli.Context) (chain *core.ChainManager, chainDb common.Database) { 464 datadir := ctx.GlobalString(DataDirFlag.Name) 465 cache := ctx.GlobalInt(CacheFlag.Name) 466 467 var err error 468 if chainDb, err = ethdb.NewLDBDatabase(filepath.Join(datadir, "chaindata"), cache); err != nil { 469 Fatalf("Could not open database: %v", err) 470 } 471 if ctx.GlobalBool(OlympicFlag.Name) { 472 InitOlympic() 473 _, err := core.WriteTestNetGenesisBlock(chainDb, 42) 474 if err != nil { 475 glog.Fatalln(err) 476 } 477 } 478 479 eventMux := new(event.TypeMux) 480 pow := ethash.New() 481 //genesis := core.GenesisBlock(uint64(ctx.GlobalInt(GenesisNonceFlag.Name)), blockDB) 482 chain, err = core.NewChainManager(chainDb, pow, eventMux) 483 if err != nil { 484 Fatalf("Could not start chainmanager: %v", err) 485 } 486 487 proc := core.NewBlockProcessor(chainDb, pow, chain, eventMux) 488 chain.SetProcessor(proc) 489 return chain, chainDb 490 } 491 492 // MakeChain creates an account manager from set command line flags. 493 func MakeAccountManager(ctx *cli.Context) *accounts.Manager { 494 dataDir := ctx.GlobalString(DataDirFlag.Name) 495 ks := crypto.NewKeyStorePassphrase(filepath.Join(dataDir, "keystore")) 496 return accounts.NewManager(ks) 497 } 498 499 func IpcSocketPath(ctx *cli.Context) (ipcpath string) { 500 if runtime.GOOS == "windows" { 501 ipcpath = common.DefaultIpcPath() 502 if ctx.GlobalIsSet(IPCPathFlag.Name) { 503 ipcpath = ctx.GlobalString(IPCPathFlag.Name) 504 } 505 } else { 506 ipcpath = common.DefaultIpcPath() 507 if ctx.GlobalIsSet(DataDirFlag.Name) { 508 ipcpath = filepath.Join(ctx.GlobalString(DataDirFlag.Name), "geth.ipc") 509 } 510 if ctx.GlobalIsSet(IPCPathFlag.Name) { 511 ipcpath = ctx.GlobalString(IPCPathFlag.Name) 512 } 513 } 514 515 return 516 } 517 518 func StartIPC(eth *eth.Ethereum, ctx *cli.Context) error { 519 config := comms.IpcConfig{ 520 Endpoint: IpcSocketPath(ctx), 521 } 522 523 initializer := func(conn net.Conn) (shared.EthereumApi, error) { 524 fe := useragent.NewRemoteFrontend(conn, eth.AccountManager()) 525 xeth := xeth.New(eth, fe) 526 codec := codec.JSON 527 528 apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec, xeth, eth) 529 if err != nil { 530 return nil, err 531 } 532 533 return api.Merge(apis...), nil 534 } 535 536 return comms.StartIpc(config, codec.JSON, initializer) 537 } 538 539 func StartRPC(eth *eth.Ethereum, ctx *cli.Context) error { 540 config := comms.HttpConfig{ 541 ListenAddress: ctx.GlobalString(RPCListenAddrFlag.Name), 542 ListenPort: uint(ctx.GlobalInt(RPCPortFlag.Name)), 543 CorsDomain: ctx.GlobalString(RPCCORSDomainFlag.Name), 544 } 545 546 xeth := xeth.New(eth, nil) 547 codec := codec.JSON 548 549 apis, err := api.ParseApiString(ctx.GlobalString(RpcApiFlag.Name), codec, xeth, eth) 550 if err != nil { 551 return err 552 } 553 554 return comms.StartHttp(config, codec, api.Merge(apis...)) 555 } 556 557 func StartPProf(ctx *cli.Context) { 558 address := fmt.Sprintf("localhost:%d", ctx.GlobalInt(PProfPortFlag.Name)) 559 go func() { 560 log.Println(http.ListenAndServe(address, nil)) 561 }() 562 } 563 564 func ParamToAddress(addr string, am *accounts.Manager) (addrHex string, err error) { 565 if !((len(addr) == 40) || (len(addr) == 42)) { // with or without 0x 566 index, err := strconv.Atoi(addr) 567 if err != nil { 568 Fatalf("Invalid account address '%s'", addr) 569 } 570 571 addrHex, err = am.AddressByIndex(index) 572 if err != nil { 573 return "", err 574 } 575 } else { 576 addrHex = addr 577 } 578 return 579 }