flags.go 15 KB

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