main.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  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. utils.SetupNetwork(ctx)
  234. // Deprecation warning.
  235. if ctx.GlobalIsSet(utils.GenesisFileFlag.Name) {
  236. common.PrintDepricationWarning("--genesis is deprecated. Switch to use 'geth init /path/to/file'")
  237. }
  238. return nil
  239. }
  240. app.After = func(ctx *cli.Context) error {
  241. logger.Flush()
  242. debug.Exit()
  243. utils.Stdin.Close() // Resets terminal mode.
  244. return nil
  245. }
  246. }
  247. func main() {
  248. if err := app.Run(os.Args); err != nil {
  249. fmt.Fprintln(os.Stderr, err)
  250. os.Exit(1)
  251. }
  252. }
  253. func makeDefaultExtra() []byte {
  254. var clientInfo = struct {
  255. Version uint
  256. Name string
  257. GoVersion string
  258. Os string
  259. }{uint(versionMajor<<16 | versionMinor<<8 | versionPatch), clientIdentifier, runtime.Version(), runtime.GOOS}
  260. extra, err := rlp.EncodeToBytes(clientInfo)
  261. if err != nil {
  262. glog.V(logger.Warn).Infoln("error setting canonical miner information:", err)
  263. }
  264. if uint64(len(extra)) > params.MaximumExtraDataSize.Uint64() {
  265. glog.V(logger.Warn).Infoln("error setting canonical miner information: extra exceeds", params.MaximumExtraDataSize)
  266. glog.V(logger.Debug).Infof("extra: %x\n", extra)
  267. return nil
  268. }
  269. return extra
  270. }
  271. // geth is the main entry point into the system if no special subcommand is ran.
  272. // It creates a default node based on the command line arguments and runs it in
  273. // blocking mode, waiting for it to be shut down.
  274. func geth(ctx *cli.Context) {
  275. node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
  276. startNode(ctx, node)
  277. node.Wait()
  278. }
  279. // attach will connect to a running geth instance attaching a JavaScript console and to it.
  280. func attach(ctx *cli.Context) {
  281. // attach to a running geth instance
  282. client, err := utils.NewRemoteRPCClient(ctx)
  283. if err != nil {
  284. utils.Fatalf("Unable to attach to geth: %v", err)
  285. }
  286. repl := newLightweightJSRE(
  287. ctx.GlobalString(utils.JSpathFlag.Name),
  288. client,
  289. ctx.GlobalString(utils.DataDirFlag.Name),
  290. true,
  291. )
  292. // preload user defined JS files into the console
  293. err = repl.preloadJSFiles(ctx)
  294. if err != nil {
  295. utils.Fatalf("unable to preload JS file %v", err)
  296. }
  297. // in case the exec flag holds a JS statement execute it and return
  298. if ctx.GlobalString(utils.ExecFlag.Name) != "" {
  299. repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
  300. } else {
  301. repl.welcome()
  302. repl.interactive()
  303. }
  304. }
  305. // initGenesis will initialise the given JSON format genesis file and writes it as
  306. // the zero'd block (i.e. genesis) or will fail hard if it can't succeed.
  307. func initGenesis(ctx *cli.Context) {
  308. genesisPath := ctx.Args().First()
  309. if len(genesisPath) == 0 {
  310. utils.Fatalf("must supply path to genesis JSON file")
  311. }
  312. chainDb, err := ethdb.NewLDBDatabase(filepath.Join(utils.MustMakeDataDir(ctx), "chaindata"), 0, 0)
  313. if err != nil {
  314. utils.Fatalf("could not open database: %v", err)
  315. }
  316. genesisFile, err := os.Open(genesisPath)
  317. if err != nil {
  318. utils.Fatalf("failed to read genesis file: %v", err)
  319. }
  320. block, err := core.WriteGenesisBlock(chainDb, genesisFile)
  321. if err != nil {
  322. utils.Fatalf("failed to write genesis block: %v", err)
  323. }
  324. glog.V(logger.Info).Infof("successfully wrote genesis block and/or chain rule set: %x", block.Hash())
  325. }
  326. // console starts a new geth node, attaching a JavaScript console to it at the
  327. // same time.
  328. func console(ctx *cli.Context) {
  329. // Create and start the node based on the CLI flags
  330. node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
  331. startNode(ctx, node)
  332. // Attach to the newly started node, and either execute script or become interactive
  333. client, err := node.Attach()
  334. if err != nil {
  335. utils.Fatalf("Failed to attach to the inproc geth: %v", err)
  336. }
  337. repl := newJSRE(node,
  338. ctx.GlobalString(utils.JSpathFlag.Name),
  339. ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
  340. client, true)
  341. // preload user defined JS files into the console
  342. err = repl.preloadJSFiles(ctx)
  343. if err != nil {
  344. utils.Fatalf("%v", err)
  345. }
  346. // in case the exec flag holds a JS statement execute it and return
  347. if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" {
  348. repl.batch(script)
  349. } else {
  350. repl.welcome()
  351. repl.interactive()
  352. }
  353. node.Stop()
  354. }
  355. // execScripts starts a new geth node based on the CLI flags, and executes each
  356. // of the JavaScript files specified as command arguments.
  357. func execScripts(ctx *cli.Context) {
  358. // Create and start the node based on the CLI flags
  359. node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
  360. startNode(ctx, node)
  361. defer node.Stop()
  362. // Attach to the newly started node and execute the given scripts
  363. client, err := node.Attach()
  364. if err != nil {
  365. utils.Fatalf("Failed to attach to the inproc geth: %v", err)
  366. }
  367. repl := newJSRE(node,
  368. ctx.GlobalString(utils.JSpathFlag.Name),
  369. ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
  370. client, false)
  371. // Run all given files.
  372. for _, file := range ctx.Args() {
  373. if err = repl.re.Exec(file); err != nil {
  374. break
  375. }
  376. }
  377. if err != nil {
  378. utils.Fatalf("JavaScript Error: %v", jsErrorString(err))
  379. }
  380. // JS files loaded successfully.
  381. // Wait for pending callbacks, but stop for Ctrl-C.
  382. abort := make(chan os.Signal, 1)
  383. signal.Notify(abort, os.Interrupt)
  384. go func() {
  385. <-abort
  386. repl.re.Stop(false)
  387. }()
  388. repl.re.Stop(true)
  389. }
  390. // startNode boots up the system node and all registered protocols, after which
  391. // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
  392. // miner.
  393. func startNode(ctx *cli.Context, stack *node.Node) {
  394. // Start up the node itself
  395. utils.StartNode(stack)
  396. // Unlock any account specifically requested
  397. var ethereum *eth.Ethereum
  398. if err := stack.Service(&ethereum); err != nil {
  399. utils.Fatalf("ethereum service not running: %v", err)
  400. }
  401. accman := ethereum.AccountManager()
  402. passwords := utils.MakePasswordList(ctx)
  403. accounts := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
  404. for i, account := range accounts {
  405. if trimmed := strings.TrimSpace(account); trimmed != "" {
  406. unlockAccount(ctx, accman, trimmed, i, passwords)
  407. }
  408. }
  409. // Start auxiliary services if enabled
  410. if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
  411. if err := ethereum.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name), ctx.GlobalString(utils.MiningGPUFlag.Name)); err != nil {
  412. utils.Fatalf("Failed to start mining: %v", err)
  413. }
  414. }
  415. }
  416. func makedag(ctx *cli.Context) {
  417. args := ctx.Args()
  418. wrongArgs := func() {
  419. utils.Fatalf(`Usage: geth makedag <block number> <outputdir>`)
  420. }
  421. switch {
  422. case len(args) == 2:
  423. blockNum, err := strconv.ParseUint(args[0], 0, 64)
  424. dir := args[1]
  425. if err != nil {
  426. wrongArgs()
  427. } else {
  428. dir = filepath.Clean(dir)
  429. // seems to require a trailing slash
  430. if !strings.HasSuffix(dir, "/") {
  431. dir = dir + "/"
  432. }
  433. _, err = ioutil.ReadDir(dir)
  434. if err != nil {
  435. utils.Fatalf("Can't find dir")
  436. }
  437. fmt.Println("making DAG, this could take awhile...")
  438. ethash.MakeDAG(blockNum, dir)
  439. }
  440. default:
  441. wrongArgs()
  442. }
  443. }
  444. func gpuinfo(ctx *cli.Context) {
  445. eth.PrintOpenCLDevices()
  446. }
  447. func gpubench(ctx *cli.Context) {
  448. args := ctx.Args()
  449. wrongArgs := func() {
  450. utils.Fatalf(`Usage: geth gpubench <gpu number>`)
  451. }
  452. switch {
  453. case len(args) == 1:
  454. n, err := strconv.ParseUint(args[0], 0, 64)
  455. if err != nil {
  456. wrongArgs()
  457. }
  458. eth.GPUBench(n)
  459. case len(args) == 0:
  460. eth.GPUBench(0)
  461. default:
  462. wrongArgs()
  463. }
  464. }
  465. func version(c *cli.Context) {
  466. fmt.Println(clientIdentifier)
  467. fmt.Println("Version:", verString)
  468. fmt.Println("Protocol Versions:", eth.ProtocolVersions)
  469. fmt.Println("Network Id:", c.GlobalInt(utils.NetworkIdFlag.Name))
  470. fmt.Println("Go Version:", runtime.Version())
  471. fmt.Println("OS:", runtime.GOOS)
  472. fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH"))
  473. fmt.Printf("GOROOT=%s\n", runtime.GOROOT())
  474. }