main.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. // Copyright 2014 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. // geth is the official command-line client for Ethereum.
  17. package main
  18. import (
  19. "encoding/hex"
  20. "fmt"
  21. "io/ioutil"
  22. "os"
  23. "os/signal"
  24. "path/filepath"
  25. "runtime"
  26. "strconv"
  27. "strings"
  28. "time"
  29. "github.com/codegangsta/cli"
  30. "github.com/ethereum/ethash"
  31. "github.com/ethereum/go-ethereum/cmd/utils"
  32. "github.com/ethereum/go-ethereum/common"
  33. "github.com/ethereum/go-ethereum/core"
  34. "github.com/ethereum/go-ethereum/eth"
  35. "github.com/ethereum/go-ethereum/ethdb"
  36. "github.com/ethereum/go-ethereum/internal/debug"
  37. "github.com/ethereum/go-ethereum/logger"
  38. "github.com/ethereum/go-ethereum/logger/glog"
  39. "github.com/ethereum/go-ethereum/metrics"
  40. "github.com/ethereum/go-ethereum/node"
  41. "github.com/ethereum/go-ethereum/params"
  42. "github.com/ethereum/go-ethereum/release"
  43. "github.com/ethereum/go-ethereum/rlp"
  44. )
  45. const (
  46. clientIdentifier = "Geth" // Client identifier to advertise over the network
  47. versionMajor = 1 // Major version component of the current release
  48. versionMinor = 5 // Minor version component of the current release
  49. versionPatch = 0 // Patch version component of the current release
  50. versionMeta = "unstable" // Version metadata to append to the version string
  51. versionOracle = "0xfa7b9770ca4cb04296cac84f37736d4041251cdf" // Ethereum address of the Geth release oracle
  52. )
  53. var (
  54. gitCommit string // Git SHA1 commit hash of the release (set via linker flags)
  55. verString string // Combined textual representation of all the version components
  56. relConfig release.Config // Structured version information and release oracle config
  57. app *cli.App
  58. )
  59. func init() {
  60. // Construct the textual version string from the individual components
  61. verString = fmt.Sprintf("%d.%d.%d", versionMajor, versionMinor, versionPatch)
  62. if versionMeta != "" {
  63. verString += "-" + versionMeta
  64. }
  65. if gitCommit != "" {
  66. verString += "-" + gitCommit[:8]
  67. }
  68. // Construct the version release oracle configuration
  69. relConfig.Oracle = common.HexToAddress(versionOracle)
  70. relConfig.Major = uint32(versionMajor)
  71. relConfig.Minor = uint32(versionMinor)
  72. relConfig.Patch = uint32(versionPatch)
  73. commit, _ := hex.DecodeString(gitCommit)
  74. copy(relConfig.Commit[:], commit)
  75. // Initialize the CLI app and start Geth
  76. app = utils.NewApp(verString, "the go-ethereum command line interface")
  77. app.Action = geth
  78. app.HideVersion = true // we have a command to print the version
  79. app.Commands = []cli.Command{
  80. importCommand,
  81. exportCommand,
  82. upgradedbCommand,
  83. removedbCommand,
  84. dumpCommand,
  85. monitorCommand,
  86. accountCommand,
  87. walletCommand,
  88. {
  89. Action: makedag,
  90. Name: "makedag",
  91. Usage: "generate ethash dag (for testing)",
  92. Description: `
  93. The makedag command generates an ethash DAG in /tmp/dag.
  94. This command exists to support the system testing project.
  95. Regular users do not need to execute it.
  96. `,
  97. },
  98. {
  99. Action: gpuinfo,
  100. Name: "gpuinfo",
  101. Usage: "gpuinfo",
  102. Description: `
  103. Prints OpenCL device info for all found GPUs.
  104. `,
  105. },
  106. {
  107. Action: gpubench,
  108. Name: "gpubench",
  109. Usage: "benchmark GPU",
  110. Description: `
  111. Runs quick benchmark on first GPU found.
  112. `,
  113. },
  114. {
  115. Action: version,
  116. Name: "version",
  117. Usage: "print ethereum version numbers",
  118. Description: `
  119. The output of this command is supposed to be machine-readable.
  120. `,
  121. },
  122. {
  123. Action: initGenesis,
  124. Name: "init",
  125. Usage: "bootstraps and initialises a new genesis block (JSON)",
  126. Description: `
  127. The init command initialises a new genesis block and definition for the network.
  128. This is a destructive action and changes the network in which you will be
  129. participating.
  130. `,
  131. },
  132. {
  133. Action: console,
  134. Name: "console",
  135. Usage: `Geth Console: interactive JavaScript environment`,
  136. Description: `
  137. The Geth console is an interactive shell for the JavaScript runtime environment
  138. which exposes a node admin interface as well as the Ðapp JavaScript API.
  139. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
  140. `,
  141. },
  142. {
  143. Action: attach,
  144. Name: "attach",
  145. Usage: `Geth Console: interactive JavaScript environment (connect to node)`,
  146. Description: `
  147. The Geth console is an interactive shell for the JavaScript runtime environment
  148. which exposes a node admin interface as well as the Ðapp JavaScript API.
  149. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console.
  150. This command allows to open a console on a running geth node.
  151. `,
  152. },
  153. {
  154. Action: execScripts,
  155. Name: "js",
  156. Usage: `executes the given JavaScript files in the Geth JavaScript VM`,
  157. Description: `
  158. The JavaScript VM exposes a node admin interface as well as the Ðapp
  159. JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
  160. `,
  161. },
  162. }
  163. app.Flags = []cli.Flag{
  164. utils.IdentityFlag,
  165. utils.UnlockedAccountFlag,
  166. utils.PasswordFileFlag,
  167. utils.GenesisFileFlag,
  168. utils.BootnodesFlag,
  169. utils.DataDirFlag,
  170. utils.KeyStoreDirFlag,
  171. utils.BlockchainVersionFlag,
  172. utils.OlympicFlag,
  173. utils.FastSyncFlag,
  174. utils.CacheFlag,
  175. utils.LightKDFFlag,
  176. utils.JSpathFlag,
  177. utils.ListenPortFlag,
  178. utils.MaxPeersFlag,
  179. utils.MaxPendingPeersFlag,
  180. utils.EtherbaseFlag,
  181. utils.GasPriceFlag,
  182. utils.MinerThreadsFlag,
  183. utils.MiningEnabledFlag,
  184. utils.MiningGPUFlag,
  185. utils.AutoDAGFlag,
  186. utils.TargetGasLimitFlag,
  187. utils.NATFlag,
  188. utils.NatspecEnabledFlag,
  189. utils.NoDiscoverFlag,
  190. utils.NodeKeyFileFlag,
  191. utils.NodeKeyHexFlag,
  192. utils.RPCEnabledFlag,
  193. utils.RPCListenAddrFlag,
  194. utils.RPCPortFlag,
  195. utils.RPCApiFlag,
  196. utils.WSEnabledFlag,
  197. utils.WSListenAddrFlag,
  198. utils.WSPortFlag,
  199. utils.WSApiFlag,
  200. utils.WSAllowedOriginsFlag,
  201. utils.IPCDisabledFlag,
  202. utils.IPCApiFlag,
  203. utils.IPCPathFlag,
  204. utils.ExecFlag,
  205. utils.PreLoadJSFlag,
  206. utils.WhisperEnabledFlag,
  207. utils.DevModeFlag,
  208. utils.TestNetFlag,
  209. utils.VMForceJitFlag,
  210. utils.VMJitCacheFlag,
  211. utils.VMEnableJitFlag,
  212. utils.NetworkIdFlag,
  213. utils.RPCCORSDomainFlag,
  214. utils.MetricsEnabledFlag,
  215. utils.FakePoWFlag,
  216. utils.SolcPathFlag,
  217. utils.GpoMinGasPriceFlag,
  218. utils.GpoMaxGasPriceFlag,
  219. utils.GpoFullBlockRatioFlag,
  220. utils.GpobaseStepDownFlag,
  221. utils.GpobaseStepUpFlag,
  222. utils.GpobaseCorrectionFactorFlag,
  223. utils.ExtraDataFlag,
  224. }
  225. app.Flags = append(app.Flags, debug.Flags...)
  226. app.Before = func(ctx *cli.Context) error {
  227. runtime.GOMAXPROCS(runtime.NumCPU())
  228. if err := debug.Setup(ctx); err != nil {
  229. return err
  230. }
  231. // Start system runtime metrics collection
  232. go metrics.CollectProcessMetrics(3 * time.Second)
  233. // This should be the only place where reporting is enabled
  234. // because it is not intended to run while testing.
  235. // In addition to this check, bad block reports are sent only
  236. // for chains with the main network genesis block and network id 1.
  237. eth.EnableBadBlockReporting = true
  238. utils.SetupNetwork(ctx)
  239. // Deprecation warning.
  240. if ctx.GlobalIsSet(utils.GenesisFileFlag.Name) {
  241. common.PrintDepricationWarning("--genesis is deprecated. Switch to use 'geth init /path/to/file'")
  242. }
  243. return nil
  244. }
  245. app.After = func(ctx *cli.Context) error {
  246. logger.Flush()
  247. debug.Exit()
  248. utils.Stdin.Close() // Resets terminal mode.
  249. return nil
  250. }
  251. }
  252. func main() {
  253. if err := app.Run(os.Args); err != nil {
  254. fmt.Fprintln(os.Stderr, err)
  255. os.Exit(1)
  256. }
  257. }
  258. func makeDefaultExtra() []byte {
  259. var clientInfo = struct {
  260. Version uint
  261. Name string
  262. GoVersion string
  263. Os string
  264. }{uint(versionMajor<<16 | versionMinor<<8 | versionPatch), clientIdentifier, runtime.Version(), runtime.GOOS}
  265. extra, err := rlp.EncodeToBytes(clientInfo)
  266. if err != nil {
  267. glog.V(logger.Warn).Infoln("error setting canonical miner information:", err)
  268. }
  269. if uint64(len(extra)) > params.MaximumExtraDataSize.Uint64() {
  270. glog.V(logger.Warn).Infoln("error setting canonical miner information: extra exceeds", params.MaximumExtraDataSize)
  271. glog.V(logger.Debug).Infof("extra: %x\n", extra)
  272. return nil
  273. }
  274. return extra
  275. }
  276. // geth is the main entry point into the system if no special subcommand is ran.
  277. // It creates a default node based on the command line arguments and runs it in
  278. // blocking mode, waiting for it to be shut down.
  279. func geth(ctx *cli.Context) {
  280. node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
  281. startNode(ctx, node)
  282. node.Wait()
  283. }
  284. // attach will connect to a running geth instance attaching a JavaScript console and to it.
  285. func attach(ctx *cli.Context) {
  286. // attach to a running geth instance
  287. client, err := utils.NewRemoteRPCClient(ctx)
  288. if err != nil {
  289. utils.Fatalf("Unable to attach to geth: %v", err)
  290. }
  291. repl := newLightweightJSRE(
  292. ctx.GlobalString(utils.JSpathFlag.Name),
  293. client,
  294. ctx.GlobalString(utils.DataDirFlag.Name),
  295. true,
  296. )
  297. // preload user defined JS files into the console
  298. err = repl.preloadJSFiles(ctx)
  299. if err != nil {
  300. utils.Fatalf("unable to preload JS file %v", err)
  301. }
  302. // in case the exec flag holds a JS statement execute it and return
  303. if ctx.GlobalString(utils.ExecFlag.Name) != "" {
  304. repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
  305. } else {
  306. repl.welcome()
  307. repl.interactive()
  308. }
  309. }
  310. // initGenesis will initialise the given JSON format genesis file and writes it as
  311. // the zero'd block (i.e. genesis) or will fail hard if it can't succeed.
  312. func initGenesis(ctx *cli.Context) {
  313. genesisPath := ctx.Args().First()
  314. if len(genesisPath) == 0 {
  315. utils.Fatalf("must supply path to genesis JSON file")
  316. }
  317. chainDb, err := ethdb.NewLDBDatabase(filepath.Join(utils.MustMakeDataDir(ctx), "chaindata"), 0, 0)
  318. if err != nil {
  319. utils.Fatalf("could not open database: %v", err)
  320. }
  321. genesisFile, err := os.Open(genesisPath)
  322. if err != nil {
  323. utils.Fatalf("failed to read genesis file: %v", err)
  324. }
  325. block, err := core.WriteGenesisBlock(chainDb, genesisFile)
  326. if err != nil {
  327. utils.Fatalf("failed to write genesis block: %v", err)
  328. }
  329. glog.V(logger.Info).Infof("successfully wrote genesis block and/or chain rule set: %x", block.Hash())
  330. }
  331. // console starts a new geth node, attaching a JavaScript console to it at the
  332. // same time.
  333. func console(ctx *cli.Context) {
  334. // Create and start the node based on the CLI flags
  335. node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
  336. startNode(ctx, node)
  337. // Attach to the newly started node, and either execute script or become interactive
  338. client, err := node.Attach()
  339. if err != nil {
  340. utils.Fatalf("Failed to attach to the inproc geth: %v", err)
  341. }
  342. repl := newJSRE(node,
  343. ctx.GlobalString(utils.JSpathFlag.Name),
  344. ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
  345. client, true)
  346. // preload user defined JS files into the console
  347. err = repl.preloadJSFiles(ctx)
  348. if err != nil {
  349. utils.Fatalf("%v", err)
  350. }
  351. // in case the exec flag holds a JS statement execute it and return
  352. if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" {
  353. repl.batch(script)
  354. } else {
  355. repl.welcome()
  356. repl.interactive()
  357. }
  358. node.Stop()
  359. }
  360. // execScripts starts a new geth node based on the CLI flags, and executes each
  361. // of the JavaScript files specified as command arguments.
  362. func execScripts(ctx *cli.Context) {
  363. // Create and start the node based on the CLI flags
  364. node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
  365. startNode(ctx, node)
  366. defer node.Stop()
  367. // Attach to the newly started node and execute the given scripts
  368. client, err := node.Attach()
  369. if err != nil {
  370. utils.Fatalf("Failed to attach to the inproc geth: %v", err)
  371. }
  372. repl := newJSRE(node,
  373. ctx.GlobalString(utils.JSpathFlag.Name),
  374. ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
  375. client, false)
  376. // Run all given files.
  377. for _, file := range ctx.Args() {
  378. if err = repl.re.Exec(file); err != nil {
  379. break
  380. }
  381. }
  382. if err != nil {
  383. utils.Fatalf("JavaScript Error: %v", jsErrorString(err))
  384. }
  385. // JS files loaded successfully.
  386. // Wait for pending callbacks, but stop for Ctrl-C.
  387. abort := make(chan os.Signal, 1)
  388. signal.Notify(abort, os.Interrupt)
  389. go func() {
  390. <-abort
  391. repl.re.Stop(false)
  392. }()
  393. repl.re.Stop(true)
  394. }
  395. // startNode boots up the system node and all registered protocols, after which
  396. // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
  397. // miner.
  398. func startNode(ctx *cli.Context, stack *node.Node) {
  399. // Start up the node itself
  400. utils.StartNode(stack)
  401. // Unlock any account specifically requested
  402. var ethereum *eth.Ethereum
  403. if err := stack.Service(&ethereum); err != nil {
  404. utils.Fatalf("ethereum service not running: %v", err)
  405. }
  406. accman := ethereum.AccountManager()
  407. passwords := utils.MakePasswordList(ctx)
  408. accounts := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
  409. for i, account := range accounts {
  410. if trimmed := strings.TrimSpace(account); trimmed != "" {
  411. unlockAccount(ctx, accman, trimmed, i, passwords)
  412. }
  413. }
  414. // Start auxiliary services if enabled
  415. if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
  416. if err := ethereum.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name), ctx.GlobalString(utils.MiningGPUFlag.Name)); err != nil {
  417. utils.Fatalf("Failed to start mining: %v", err)
  418. }
  419. }
  420. }
  421. func makedag(ctx *cli.Context) {
  422. args := ctx.Args()
  423. wrongArgs := func() {
  424. utils.Fatalf(`Usage: geth makedag <block number> <outputdir>`)
  425. }
  426. switch {
  427. case len(args) == 2:
  428. blockNum, err := strconv.ParseUint(args[0], 0, 64)
  429. dir := args[1]
  430. if err != nil {
  431. wrongArgs()
  432. } else {
  433. dir = filepath.Clean(dir)
  434. // seems to require a trailing slash
  435. if !strings.HasSuffix(dir, "/") {
  436. dir = dir + "/"
  437. }
  438. _, err = ioutil.ReadDir(dir)
  439. if err != nil {
  440. utils.Fatalf("Can't find dir")
  441. }
  442. fmt.Println("making DAG, this could take awhile...")
  443. ethash.MakeDAG(blockNum, dir)
  444. }
  445. default:
  446. wrongArgs()
  447. }
  448. }
  449. func gpuinfo(ctx *cli.Context) {
  450. eth.PrintOpenCLDevices()
  451. }
  452. func gpubench(ctx *cli.Context) {
  453. args := ctx.Args()
  454. wrongArgs := func() {
  455. utils.Fatalf(`Usage: geth gpubench <gpu number>`)
  456. }
  457. switch {
  458. case len(args) == 1:
  459. n, err := strconv.ParseUint(args[0], 0, 64)
  460. if err != nil {
  461. wrongArgs()
  462. }
  463. eth.GPUBench(n)
  464. case len(args) == 0:
  465. eth.GPUBench(0)
  466. default:
  467. wrongArgs()
  468. }
  469. }
  470. func version(c *cli.Context) {
  471. fmt.Println(clientIdentifier)
  472. fmt.Println("Version:", verString)
  473. fmt.Println("Protocol Versions:", eth.ProtocolVersions)
  474. fmt.Println("Network Id:", c.GlobalInt(utils.NetworkIdFlag.Name))
  475. fmt.Println("Go Version:", runtime.Version())
  476. fmt.Println("OS:", runtime.GOOS)
  477. fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH"))
  478. fmt.Printf("GOROOT=%s\n", runtime.GOROOT())
  479. }