flags.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  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. package utils
  17. import (
  18. "crypto/ecdsa"
  19. "errors"
  20. "fmt"
  21. "io/ioutil"
  22. "math"
  23. "math/big"
  24. "os"
  25. "path/filepath"
  26. "runtime"
  27. "strconv"
  28. "strings"
  29. "github.com/codegangsta/cli"
  30. "github.com/ethereum/ethash"
  31. "github.com/ethereum/go-ethereum/accounts"
  32. "github.com/ethereum/go-ethereum/common"
  33. "github.com/ethereum/go-ethereum/core"
  34. "github.com/ethereum/go-ethereum/core/state"
  35. "github.com/ethereum/go-ethereum/core/vm"
  36. "github.com/ethereum/go-ethereum/crypto"
  37. "github.com/ethereum/go-ethereum/eth"
  38. "github.com/ethereum/go-ethereum/ethdb"
  39. "github.com/ethereum/go-ethereum/event"
  40. "github.com/ethereum/go-ethereum/logger"
  41. "github.com/ethereum/go-ethereum/logger/glog"
  42. "github.com/ethereum/go-ethereum/metrics"
  43. "github.com/ethereum/go-ethereum/node"
  44. "github.com/ethereum/go-ethereum/p2p/discover"
  45. "github.com/ethereum/go-ethereum/p2p/nat"
  46. "github.com/ethereum/go-ethereum/params"
  47. "github.com/ethereum/go-ethereum/rpc"
  48. "github.com/ethereum/go-ethereum/whisper"
  49. )
  50. func init() {
  51. cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
  52. VERSION:
  53. {{.Version}}
  54. COMMANDS:
  55. {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
  56. {{end}}{{if .Flags}}
  57. GLOBAL OPTIONS:
  58. {{range .Flags}}{{.}}
  59. {{end}}{{end}}
  60. `
  61. cli.CommandHelpTemplate = `{{.Name}}{{if .Subcommands}} command{{end}}{{if .Flags}} [command options]{{end}} [arguments...]
  62. {{if .Description}}{{.Description}}
  63. {{end}}{{if .Subcommands}}
  64. SUBCOMMANDS:
  65. {{range .Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
  66. {{end}}{{end}}{{if .Flags}}
  67. OPTIONS:
  68. {{range .Flags}}{{.}}
  69. {{end}}{{end}}
  70. `
  71. }
  72. // NewApp creates an app with sane defaults.
  73. func NewApp(version, usage string) *cli.App {
  74. app := cli.NewApp()
  75. app.Name = filepath.Base(os.Args[0])
  76. app.Author = ""
  77. //app.Authors = nil
  78. app.Email = ""
  79. app.Version = version
  80. app.Usage = usage
  81. return app
  82. }
  83. // These are all the command line flags we support.
  84. // If you add to this list, please remember to include the
  85. // flag in the appropriate command definition.
  86. //
  87. // The flags are defined here so their names and help texts
  88. // are the same for all commands.
  89. var (
  90. // General settings
  91. DataDirFlag = DirectoryFlag{
  92. Name: "datadir",
  93. Usage: "Data directory for the databases and keystore",
  94. Value: DirectoryString{common.DefaultDataDir()},
  95. }
  96. NetworkIdFlag = cli.IntFlag{
  97. Name: "networkid",
  98. Usage: "Network identifier (integer, 0=Olympic, 1=Frontier, 2=Morden)",
  99. Value: eth.NetworkId,
  100. }
  101. OlympicFlag = cli.BoolFlag{
  102. Name: "olympic",
  103. Usage: "Olympic network: pre-configured pre-release test network",
  104. }
  105. TestNetFlag = cli.BoolFlag{
  106. Name: "testnet",
  107. Usage: "Morden network: pre-configured test network with modified starting nonces (replay protection)",
  108. }
  109. DevModeFlag = cli.BoolFlag{
  110. Name: "dev",
  111. Usage: "Developer mode: pre-configured private network with several debugging flags",
  112. }
  113. GenesisFileFlag = cli.StringFlag{
  114. Name: "genesis",
  115. Usage: "Insert/overwrite the genesis block (JSON format)",
  116. }
  117. IdentityFlag = cli.StringFlag{
  118. Name: "identity",
  119. Usage: "Custom node name",
  120. }
  121. NatspecEnabledFlag = cli.BoolFlag{
  122. Name: "natspec",
  123. Usage: "Enable NatSpec confirmation notice",
  124. }
  125. DocRootFlag = DirectoryFlag{
  126. Name: "docroot",
  127. Usage: "Document Root for HTTPClient file scheme",
  128. Value: DirectoryString{common.HomeDir()},
  129. }
  130. CacheFlag = cli.IntFlag{
  131. Name: "cache",
  132. Usage: "Megabytes of memory allocated to internal caching (min 16MB / database forced)",
  133. Value: 0,
  134. }
  135. BlockchainVersionFlag = cli.IntFlag{
  136. Name: "blockchainversion",
  137. Usage: "Blockchain version (integer)",
  138. Value: core.BlockChainVersion,
  139. }
  140. FastSyncFlag = cli.BoolFlag{
  141. Name: "fast",
  142. Usage: "Enable fast syncing through state downloads",
  143. }
  144. LightKDFFlag = cli.BoolFlag{
  145. Name: "lightkdf",
  146. Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
  147. }
  148. // Miner settings
  149. // TODO: refactor CPU vs GPU mining flags
  150. MiningEnabledFlag = cli.BoolFlag{
  151. Name: "mine",
  152. Usage: "Enable mining",
  153. }
  154. MinerThreadsFlag = cli.IntFlag{
  155. Name: "minerthreads",
  156. Usage: "Number of CPU threads to use for mining",
  157. Value: runtime.NumCPU(),
  158. }
  159. MiningGPUFlag = cli.StringFlag{
  160. Name: "minergpus",
  161. Usage: "List of GPUs to use for mining (e.g. '0,1' will use the first two GPUs found)",
  162. }
  163. AutoDAGFlag = cli.BoolFlag{
  164. Name: "autodag",
  165. Usage: "Enable automatic DAG pregeneration",
  166. }
  167. EtherbaseFlag = cli.StringFlag{
  168. Name: "etherbase",
  169. Usage: "Public address for block mining rewards (default = first account created)",
  170. Value: "0",
  171. }
  172. GasPriceFlag = cli.StringFlag{
  173. Name: "gasprice",
  174. Usage: "Minimal gas price to accept for mining a transactions",
  175. Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(),
  176. }
  177. ExtraDataFlag = cli.StringFlag{
  178. Name: "extradata",
  179. Usage: "Block extra data set by the miner (default = client version)",
  180. }
  181. // Account settings
  182. UnlockedAccountFlag = cli.StringFlag{
  183. Name: "unlock",
  184. Usage: "Comma separated list of accounts to unlock",
  185. Value: "",
  186. }
  187. PasswordFileFlag = cli.StringFlag{
  188. Name: "password",
  189. Usage: "Password file to use for non-inteactive password input",
  190. Value: "",
  191. }
  192. // vm flags
  193. VMDebugFlag = cli.BoolFlag{
  194. Name: "vmdebug",
  195. Usage: "Virtual Machine debug output",
  196. }
  197. VMForceJitFlag = cli.BoolFlag{
  198. Name: "forcejit",
  199. Usage: "Force the JIT VM to take precedence",
  200. }
  201. VMJitCacheFlag = cli.IntFlag{
  202. Name: "jitcache",
  203. Usage: "Amount of cached JIT VM programs",
  204. Value: 64,
  205. }
  206. VMEnableJitFlag = cli.BoolFlag{
  207. Name: "jitvm",
  208. Usage: "Enable the JIT VM",
  209. }
  210. // logging and debug settings
  211. MetricsEnabledFlag = cli.BoolFlag{
  212. Name: metrics.MetricsEnabledFlag,
  213. Usage: "Enable metrics collection and reporting",
  214. }
  215. // RPC settings
  216. RPCEnabledFlag = cli.BoolFlag{
  217. Name: "rpc",
  218. Usage: "Enable the HTTP-RPC server",
  219. }
  220. RPCListenAddrFlag = cli.StringFlag{
  221. Name: "rpcaddr",
  222. Usage: "HTTP-RPC server listening interface",
  223. Value: "127.0.0.1",
  224. }
  225. RPCPortFlag = cli.IntFlag{
  226. Name: "rpcport",
  227. Usage: "HTTP-RPC server listening port",
  228. Value: 8545,
  229. }
  230. RPCCORSDomainFlag = cli.StringFlag{
  231. Name: "rpccorsdomain",
  232. Usage: "Domains from which to accept cross origin requests (browser enforced)",
  233. Value: "",
  234. }
  235. RPCApiFlag = cli.StringFlag{
  236. Name: "rpcapi",
  237. Usage: "API's offered over the HTTP-RPC interface",
  238. Value: rpc.DefaultHttpRpcApis,
  239. }
  240. IPCDisabledFlag = cli.BoolFlag{
  241. Name: "ipcdisable",
  242. Usage: "Disable the IPC-RPC server",
  243. }
  244. IPCApiFlag = cli.StringFlag{
  245. Name: "ipcapi",
  246. Usage: "API's offered over the IPC-RPC interface",
  247. Value: rpc.DefaultIpcApis,
  248. }
  249. IPCPathFlag = DirectoryFlag{
  250. Name: "ipcpath",
  251. Usage: "Filename for IPC socket/pipe",
  252. Value: DirectoryString{common.DefaultIpcPath()},
  253. }
  254. WSEnabledFlag = cli.BoolFlag{
  255. Name: "ws",
  256. Usage: "Enable the WS-RPC server",
  257. }
  258. WSListenAddrFlag = cli.StringFlag{
  259. Name: "wsaddr",
  260. Usage: "WS-RPC server listening interface",
  261. Value: "127.0.0.1",
  262. }
  263. WSPortFlag = cli.IntFlag{
  264. Name: "wsport",
  265. Usage: "WS-RPC server listening port",
  266. Value: 8546,
  267. }
  268. WSApiFlag = cli.StringFlag{
  269. Name: "wsapi",
  270. Usage: "API's offered over the WS-RPC interface",
  271. Value: rpc.DefaultHttpRpcApis,
  272. }
  273. WSAllowedDomainsFlag = cli.StringFlag{
  274. Name: "wsdomains",
  275. Usage: "Domains from which to accept websockets requests",
  276. Value: "",
  277. }
  278. ExecFlag = cli.StringFlag{
  279. Name: "exec",
  280. Usage: "Execute JavaScript statement (only in combination with console/attach)",
  281. }
  282. // Network Settings
  283. MaxPeersFlag = cli.IntFlag{
  284. Name: "maxpeers",
  285. Usage: "Maximum number of network peers (network disabled if set to 0)",
  286. Value: 25,
  287. }
  288. MaxPendingPeersFlag = cli.IntFlag{
  289. Name: "maxpendpeers",
  290. Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
  291. Value: 0,
  292. }
  293. ListenPortFlag = cli.IntFlag{
  294. Name: "port",
  295. Usage: "Network listening port",
  296. Value: 30303,
  297. }
  298. BootnodesFlag = cli.StringFlag{
  299. Name: "bootnodes",
  300. Usage: "Comma separated enode URLs for P2P discovery bootstrap",
  301. Value: "",
  302. }
  303. NodeKeyFileFlag = cli.StringFlag{
  304. Name: "nodekey",
  305. Usage: "P2P node key file",
  306. }
  307. NodeKeyHexFlag = cli.StringFlag{
  308. Name: "nodekeyhex",
  309. Usage: "P2P node key as hex (for testing)",
  310. }
  311. NATFlag = cli.StringFlag{
  312. Name: "nat",
  313. Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
  314. Value: "any",
  315. }
  316. NoDiscoverFlag = cli.BoolFlag{
  317. Name: "nodiscover",
  318. Usage: "Disables the peer discovery mechanism (manual peer addition)",
  319. }
  320. WhisperEnabledFlag = cli.BoolFlag{
  321. Name: "shh",
  322. Usage: "Enable Whisper",
  323. }
  324. // ATM the url is left to the user and deployment to
  325. JSpathFlag = cli.StringFlag{
  326. Name: "jspath",
  327. Usage: "JavaSript root path for `loadScript` and document root for `admin.httpGet`",
  328. Value: ".",
  329. }
  330. SolcPathFlag = cli.StringFlag{
  331. Name: "solc",
  332. Usage: "Solidity compiler command to be used",
  333. Value: "solc",
  334. }
  335. // Gas price oracle settings
  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. // MustMakeDataDir retrieves the currently requested data directory, terminating
  368. // if none (or the empty string) is specified. If the node is starting a testnet,
  369. // the a subdirectory of the specified datadir will be used.
  370. func MustMakeDataDir(ctx *cli.Context) string {
  371. if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
  372. if ctx.GlobalBool(TestNetFlag.Name) {
  373. return filepath.Join(path, "/testnet")
  374. }
  375. return path
  376. }
  377. Fatalf("Cannot determine default data directory, please set manually (--datadir)")
  378. return ""
  379. }
  380. // MakeNodeKey creates a node key from set command line flags, either loading it
  381. // from a file or as a specified hex value. If neither flags were provided, this
  382. // method returns nil and an emphemeral key is to be generated.
  383. func MakeNodeKey(ctx *cli.Context) *ecdsa.PrivateKey {
  384. var (
  385. hex = ctx.GlobalString(NodeKeyHexFlag.Name)
  386. file = ctx.GlobalString(NodeKeyFileFlag.Name)
  387. key *ecdsa.PrivateKey
  388. err error
  389. )
  390. switch {
  391. case file != "" && hex != "":
  392. Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
  393. case file != "":
  394. if key, err = crypto.LoadECDSA(file); err != nil {
  395. Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
  396. }
  397. case hex != "":
  398. if key, err = crypto.HexToECDSA(hex); err != nil {
  399. Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
  400. }
  401. }
  402. return key
  403. }
  404. // MakeNodeName creates a node name from a base set and the command line flags.
  405. func MakeNodeName(client, version string, ctx *cli.Context) string {
  406. name := common.MakeName(client, version)
  407. if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
  408. name += "/" + identity
  409. }
  410. if ctx.GlobalBool(VMEnableJitFlag.Name) {
  411. name += "/JIT"
  412. }
  413. return name
  414. }
  415. // MakeBootstrapNodes creates a list of bootstrap nodes from the command line
  416. // flags, reverting to pre-configured ones if none have been specified.
  417. func MakeBootstrapNodes(ctx *cli.Context) []*discover.Node {
  418. // Return pre-configured nodes if none were manually requested
  419. if !ctx.GlobalIsSet(BootnodesFlag.Name) {
  420. if ctx.GlobalBool(TestNetFlag.Name) {
  421. return TestNetBootNodes
  422. }
  423. return FrontierBootNodes
  424. }
  425. // Otherwise parse and use the CLI bootstrap nodes
  426. bootnodes := []*discover.Node{}
  427. for _, url := range strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") {
  428. node, err := discover.ParseNode(url)
  429. if err != nil {
  430. glog.V(logger.Error).Infof("Bootstrap URL %s: %v\n", url, err)
  431. continue
  432. }
  433. bootnodes = append(bootnodes, node)
  434. }
  435. return bootnodes
  436. }
  437. // MakeListenAddress creates a TCP listening address string from set command
  438. // line flags.
  439. func MakeListenAddress(ctx *cli.Context) string {
  440. return fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
  441. }
  442. // MakeNAT creates a port mapper from set command line flags.
  443. func MakeNAT(ctx *cli.Context) nat.Interface {
  444. natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
  445. if err != nil {
  446. Fatalf("Option %s: %v", NATFlag.Name, err)
  447. }
  448. return natif
  449. }
  450. // MakeGenesisBlock loads up a genesis block from an input file specified in the
  451. // command line, or returns the empty string if none set.
  452. func MakeGenesisBlock(ctx *cli.Context) string {
  453. genesis := ctx.GlobalString(GenesisFileFlag.Name)
  454. if genesis == "" {
  455. return ""
  456. }
  457. data, err := ioutil.ReadFile(genesis)
  458. if err != nil {
  459. Fatalf("Failed to load custom genesis file: %v", err)
  460. }
  461. return string(data)
  462. }
  463. // MakeAccountManager creates an account manager from set command line flags.
  464. func MakeAccountManager(ctx *cli.Context) *accounts.Manager {
  465. // Create the keystore crypto primitive, light if requested
  466. scryptN := crypto.StandardScryptN
  467. scryptP := crypto.StandardScryptP
  468. if ctx.GlobalBool(LightKDFFlag.Name) {
  469. scryptN = crypto.LightScryptN
  470. scryptP = crypto.LightScryptP
  471. }
  472. // Assemble an account manager using the configured datadir
  473. var (
  474. datadir = MustMakeDataDir(ctx)
  475. keystore = crypto.NewKeyStorePassphrase(filepath.Join(datadir, "keystore"), scryptN, scryptP)
  476. )
  477. return accounts.NewManager(keystore)
  478. }
  479. // MakeAddress converts an account specified directly as a hex encoded string or
  480. // a key index in the key store to an internal account representation.
  481. func MakeAddress(accman *accounts.Manager, account string) (a common.Address, err error) {
  482. // If the specified account is a valid address, return it
  483. if common.IsHexAddress(account) {
  484. return common.HexToAddress(account), nil
  485. }
  486. // Otherwise try to interpret the account as a keystore index
  487. index, err := strconv.Atoi(account)
  488. if err != nil {
  489. return a, fmt.Errorf("invalid account address or index %q", account)
  490. }
  491. hex, err := accman.AddressByIndex(index)
  492. if err != nil {
  493. return a, fmt.Errorf("can't get account #%d (%v)", index, err)
  494. }
  495. return common.HexToAddress(hex), nil
  496. }
  497. // MakeEtherbase retrieves the etherbase either from the directly specified
  498. // command line flags or from the keystore if CLI indexed.
  499. func MakeEtherbase(accman *accounts.Manager, ctx *cli.Context) common.Address {
  500. accounts, _ := accman.Accounts()
  501. if !ctx.GlobalIsSet(EtherbaseFlag.Name) && len(accounts) == 0 {
  502. glog.V(logger.Error).Infoln("WARNING: No etherbase set and no accounts found as default")
  503. return common.Address{}
  504. }
  505. etherbase := ctx.GlobalString(EtherbaseFlag.Name)
  506. if etherbase == "" {
  507. return common.Address{}
  508. }
  509. // If the specified etherbase is a valid address, return it
  510. addr, err := MakeAddress(accman, etherbase)
  511. if err != nil {
  512. Fatalf("Option %q: %v", EtherbaseFlag.Name, err)
  513. }
  514. return addr
  515. }
  516. // MakeMinerExtra resolves extradata for the miner from the set command line flags
  517. // or returns a default one composed on the client, runtime and OS metadata.
  518. func MakeMinerExtra(extra []byte, ctx *cli.Context) []byte {
  519. if ctx.GlobalIsSet(ExtraDataFlag.Name) {
  520. return []byte(ctx.GlobalString(ExtraDataFlag.Name))
  521. }
  522. return extra
  523. }
  524. // MakePasswordList loads up a list of password from a file specified by the
  525. // command line flags.
  526. func MakePasswordList(ctx *cli.Context) []string {
  527. if path := ctx.GlobalString(PasswordFileFlag.Name); path != "" {
  528. blob, err := ioutil.ReadFile(path)
  529. if err != nil {
  530. Fatalf("Failed to read password file: %v", err)
  531. }
  532. return strings.Split(string(blob), "\n")
  533. }
  534. return nil
  535. }
  536. // MakeSystemNode sets up a local node, configures the services to launch and
  537. // assembles the P2P protocol stack.
  538. func MakeSystemNode(name, version string, extra []byte, ctx *cli.Context) *node.Node {
  539. // Avoid conflicting network flags
  540. networks, netFlags := 0, []cli.BoolFlag{DevModeFlag, TestNetFlag, OlympicFlag}
  541. for _, flag := range netFlags {
  542. if ctx.GlobalBool(flag.Name) {
  543. networks++
  544. }
  545. }
  546. if networks > 1 {
  547. Fatalf("The %v flags are mutually exclusive", netFlags)
  548. }
  549. // Configure the node's service container
  550. stackConf := &node.Config{
  551. DataDir: MustMakeDataDir(ctx),
  552. PrivateKey: MakeNodeKey(ctx),
  553. Name: MakeNodeName(name, version, ctx),
  554. NoDiscovery: ctx.GlobalBool(NoDiscoverFlag.Name),
  555. BootstrapNodes: MakeBootstrapNodes(ctx),
  556. ListenAddr: MakeListenAddress(ctx),
  557. NAT: MakeNAT(ctx),
  558. MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
  559. MaxPendingPeers: ctx.GlobalInt(MaxPendingPeersFlag.Name),
  560. }
  561. // Configure the Ethereum service
  562. accman := MakeAccountManager(ctx)
  563. ethConf := &eth.Config{
  564. Genesis: MakeGenesisBlock(ctx),
  565. FastSync: ctx.GlobalBool(FastSyncFlag.Name),
  566. BlockChainVersion: ctx.GlobalInt(BlockchainVersionFlag.Name),
  567. DatabaseCache: ctx.GlobalInt(CacheFlag.Name),
  568. NetworkId: ctx.GlobalInt(NetworkIdFlag.Name),
  569. AccountManager: accman,
  570. Etherbase: MakeEtherbase(accman, ctx),
  571. MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
  572. ExtraData: MakeMinerExtra(extra, ctx),
  573. NatSpec: ctx.GlobalBool(NatspecEnabledFlag.Name),
  574. DocRoot: ctx.GlobalString(DocRootFlag.Name),
  575. GasPrice: common.String2Big(ctx.GlobalString(GasPriceFlag.Name)),
  576. GpoMinGasPrice: common.String2Big(ctx.GlobalString(GpoMinGasPriceFlag.Name)),
  577. GpoMaxGasPrice: common.String2Big(ctx.GlobalString(GpoMaxGasPriceFlag.Name)),
  578. GpoFullBlockRatio: ctx.GlobalInt(GpoFullBlockRatioFlag.Name),
  579. GpobaseStepDown: ctx.GlobalInt(GpobaseStepDownFlag.Name),
  580. GpobaseStepUp: ctx.GlobalInt(GpobaseStepUpFlag.Name),
  581. GpobaseCorrectionFactor: ctx.GlobalInt(GpobaseCorrectionFactorFlag.Name),
  582. SolcPath: ctx.GlobalString(SolcPathFlag.Name),
  583. AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name),
  584. }
  585. // Configure the Whisper service
  586. shhEnable := ctx.GlobalBool(WhisperEnabledFlag.Name)
  587. // Override any default configs in dev mode or the test net
  588. switch {
  589. case ctx.GlobalBool(OlympicFlag.Name):
  590. if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  591. ethConf.NetworkId = 1
  592. }
  593. if !ctx.GlobalIsSet(GenesisFileFlag.Name) {
  594. ethConf.Genesis = core.OlympicGenesisBlock()
  595. }
  596. case ctx.GlobalBool(TestNetFlag.Name):
  597. if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  598. ethConf.NetworkId = 2
  599. }
  600. if !ctx.GlobalIsSet(GenesisFileFlag.Name) {
  601. ethConf.Genesis = core.TestNetGenesisBlock()
  602. }
  603. state.StartingNonce = 1048576 // (2**20)
  604. case ctx.GlobalBool(DevModeFlag.Name):
  605. // Override the base network stack configs
  606. if !ctx.GlobalIsSet(DataDirFlag.Name) {
  607. stackConf.DataDir = filepath.Join(os.TempDir(), "/ethereum_dev_mode")
  608. }
  609. if !ctx.GlobalIsSet(MaxPeersFlag.Name) {
  610. stackConf.MaxPeers = 0
  611. }
  612. if !ctx.GlobalIsSet(ListenPortFlag.Name) {
  613. stackConf.ListenAddr = ":0"
  614. }
  615. // Override the Ethereum protocol configs
  616. if !ctx.GlobalIsSet(GenesisFileFlag.Name) {
  617. ethConf.Genesis = core.OlympicGenesisBlock()
  618. }
  619. if !ctx.GlobalIsSet(GasPriceFlag.Name) {
  620. ethConf.GasPrice = new(big.Int)
  621. }
  622. if !ctx.GlobalIsSet(WhisperEnabledFlag.Name) {
  623. shhEnable = true
  624. }
  625. if !ctx.GlobalIsSet(VMDebugFlag.Name) {
  626. vm.Debug = true
  627. }
  628. ethConf.PowTest = true
  629. }
  630. // Assemble and return the protocol stack
  631. stack, err := node.New(stackConf)
  632. if err != nil {
  633. Fatalf("Failed to create the protocol stack: %v", err)
  634. }
  635. if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  636. return eth.New(ctx, ethConf)
  637. }); err != nil {
  638. Fatalf("Failed to register the Ethereum service: %v", err)
  639. }
  640. if shhEnable {
  641. if err := stack.Register(func(*node.ServiceContext) (node.Service, error) { return whisper.New(), nil }); err != nil {
  642. Fatalf("Failed to register the Whisper service: %v", err)
  643. }
  644. }
  645. return stack
  646. }
  647. // SetupNetwork configures the system for either the main net or some test network.
  648. func SetupNetwork(ctx *cli.Context) {
  649. switch {
  650. case ctx.GlobalBool(OlympicFlag.Name):
  651. params.DurationLimit = big.NewInt(8)
  652. params.GenesisGasLimit = big.NewInt(3141592)
  653. params.MinGasLimit = big.NewInt(125000)
  654. params.MaximumExtraDataSize = big.NewInt(1024)
  655. NetworkIdFlag.Value = 0
  656. core.BlockReward = big.NewInt(1.5e+18)
  657. core.ExpDiffPeriod = big.NewInt(math.MaxInt64)
  658. }
  659. }
  660. // SetupVM configured the VM package's global settings
  661. func SetupVM(ctx *cli.Context) {
  662. vm.EnableJit = ctx.GlobalBool(VMEnableJitFlag.Name)
  663. vm.ForceJit = ctx.GlobalBool(VMForceJitFlag.Name)
  664. vm.SetJITCacheSize(ctx.GlobalInt(VMJitCacheFlag.Name))
  665. if ctx.GlobalIsSet(VMDebugFlag.Name) {
  666. vm.Debug = ctx.GlobalBool(VMDebugFlag.Name)
  667. }
  668. }
  669. // MakeChain creates a chain manager from set command line flags.
  670. func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database) {
  671. datadir := MustMakeDataDir(ctx)
  672. cache := ctx.GlobalInt(CacheFlag.Name)
  673. var err error
  674. if chainDb, err = ethdb.NewLDBDatabase(filepath.Join(datadir, "chaindata"), cache); err != nil {
  675. Fatalf("Could not open database: %v", err)
  676. }
  677. if ctx.GlobalBool(OlympicFlag.Name) {
  678. _, err := core.WriteTestNetGenesisBlock(chainDb)
  679. if err != nil {
  680. glog.Fatalln(err)
  681. }
  682. }
  683. eventMux := new(event.TypeMux)
  684. pow := ethash.New()
  685. //genesis := core.GenesisBlock(uint64(ctx.GlobalInt(GenesisNonceFlag.Name)), blockDB)
  686. chain, err = core.NewBlockChain(chainDb, pow, eventMux)
  687. if err != nil {
  688. Fatalf("Could not start chainmanager: %v", err)
  689. }
  690. return chain, chainDb
  691. }
  692. func IPCSocketPath(ctx *cli.Context) (ipcpath string) {
  693. if runtime.GOOS == "windows" {
  694. ipcpath = common.DefaultIpcPath()
  695. if ctx.GlobalIsSet(IPCPathFlag.Name) {
  696. ipcpath = ctx.GlobalString(IPCPathFlag.Name)
  697. }
  698. } else {
  699. ipcpath = common.DefaultIpcPath()
  700. if ctx.GlobalIsSet(DataDirFlag.Name) {
  701. ipcpath = filepath.Join(ctx.GlobalString(DataDirFlag.Name), "geth.ipc")
  702. }
  703. if ctx.GlobalIsSet(IPCPathFlag.Name) {
  704. ipcpath = ctx.GlobalString(IPCPathFlag.Name)
  705. }
  706. }
  707. return
  708. }
  709. func StartIPC(stack *node.Node, ctx *cli.Context) error {
  710. var ethereum *eth.Ethereum
  711. if err := stack.Service(&ethereum); err != nil {
  712. return err
  713. }
  714. endpoint := IPCSocketPath(ctx)
  715. listener, err := rpc.CreateIPCListener(endpoint)
  716. if err != nil {
  717. return err
  718. }
  719. server := rpc.NewServer()
  720. // register package API's this node provides
  721. offered := stack.APIs()
  722. for _, api := range offered {
  723. server.RegisterName(api.Namespace, api.Service)
  724. glog.V(logger.Debug).Infof("Register %T under namespace '%s' for IPC service\n", api.Service, api.Namespace)
  725. }
  726. go func() {
  727. glog.V(logger.Info).Infof("Start IPC server on %s\n", endpoint)
  728. for {
  729. conn, err := listener.Accept()
  730. if err != nil {
  731. glog.V(logger.Error).Infof("Unable to accept connection - %v\n", err)
  732. }
  733. codec := rpc.NewJSONCodec(conn)
  734. go server.ServeCodec(codec)
  735. }
  736. }()
  737. return nil
  738. }
  739. // StartRPC starts a HTTP JSON-RPC API server.
  740. func StartRPC(stack *node.Node, ctx *cli.Context) error {
  741. for _, api := range stack.APIs() {
  742. if adminApi, ok := api.Service.(*node.PrivateAdminAPI); ok {
  743. address := ctx.GlobalString(RPCListenAddrFlag.Name)
  744. port := ctx.GlobalInt(RPCPortFlag.Name)
  745. cors := ctx.GlobalString(RPCCORSDomainFlag.Name)
  746. apiStr := ""
  747. if ctx.GlobalIsSet(RPCApiFlag.Name) {
  748. apiStr = ctx.GlobalString(RPCApiFlag.Name)
  749. }
  750. _, err := adminApi.StartRPC(address, port, cors, apiStr)
  751. return err
  752. }
  753. }
  754. glog.V(logger.Error).Infof("Unable to start RPC-HTTP interface, could not find admin API")
  755. return errors.New("Unable to start RPC-HTTP interface")
  756. }
  757. // StartWS starts a websocket JSON-RPC API server.
  758. func StartWS(stack *node.Node, ctx *cli.Context) error {
  759. for _, api := range stack.APIs() {
  760. if adminApi, ok := api.Service.(*node.PrivateAdminAPI); ok {
  761. address := ctx.GlobalString(WSListenAddrFlag.Name)
  762. port := ctx.GlobalInt(WSAllowedDomainsFlag.Name)
  763. allowedDomains := ctx.GlobalString(WSAllowedDomainsFlag.Name)
  764. apiStr := ""
  765. if ctx.GlobalIsSet(WSApiFlag.Name) {
  766. apiStr = ctx.GlobalString(WSApiFlag.Name)
  767. }
  768. _, err := adminApi.StartWS(address, port, allowedDomains, apiStr)
  769. return err
  770. }
  771. }
  772. glog.V(logger.Error).Infof("Unable to start RPC-WS interface, could not find admin API")
  773. return errors.New("Unable to start RPC-WS interface")
  774. }