backend.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. // Copyright 2014 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser 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. // The go-ethereum library 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 Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. // Package eth implements the Ethereum protocol.
  17. package eth
  18. import (
  19. "bytes"
  20. "crypto/ecdsa"
  21. "encoding/json"
  22. "fmt"
  23. "io/ioutil"
  24. "math/big"
  25. "os"
  26. "path/filepath"
  27. "strings"
  28. "time"
  29. "github.com/ethereum/ethash"
  30. "github.com/ethereum/go-ethereum/accounts"
  31. "github.com/ethereum/go-ethereum/common"
  32. "github.com/ethereum/go-ethereum/common/compiler"
  33. "github.com/ethereum/go-ethereum/core"
  34. "github.com/ethereum/go-ethereum/core/state"
  35. "github.com/ethereum/go-ethereum/core/types"
  36. "github.com/ethereum/go-ethereum/core/vm"
  37. "github.com/ethereum/go-ethereum/crypto"
  38. "github.com/ethereum/go-ethereum/eth/downloader"
  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/miner"
  44. "github.com/ethereum/go-ethereum/p2p"
  45. "github.com/ethereum/go-ethereum/p2p/discover"
  46. "github.com/ethereum/go-ethereum/p2p/nat"
  47. "github.com/ethereum/go-ethereum/whisper"
  48. )
  49. const (
  50. epochLength = 30000
  51. ethashRevision = 23
  52. autoDAGcheckInterval = 10 * time.Hour
  53. autoDAGepochHeight = epochLength / 2
  54. )
  55. var (
  56. jsonlogger = logger.NewJsonLogger()
  57. defaultBootNodes = []*discover.Node{
  58. // ETH/DEV Go Bootnodes
  59. discover.MustParseNode("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303"), // IE
  60. discover.MustParseNode("enode://de471bccee3d042261d52e9bff31458daecc406142b401d4cd848f677479f73104b9fdeb090af9583d3391b7f10cb2ba9e26865dd5fca4fcdc0fb1e3b723c786@54.94.239.50:30303"), // BR
  61. discover.MustParseNode("enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303"), // SG
  62. // ETH/DEV cpp-ethereum (poc-9.ethdev.com)
  63. discover.MustParseNode("enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303"),
  64. }
  65. defaultTestNetBootNodes = []*discover.Node{
  66. discover.MustParseNode("enode://5374c1bff8df923d3706357eeb4983cd29a63be40a269aaa2296ee5f3b2119a8978c0ed68b8f6fc84aad0df18790417daadf91a4bfbb786a16c9b0a199fa254a@92.51.165.126:30303"),
  67. }
  68. staticNodes = "static-nodes.json" // Path within <datadir> to search for the static node list
  69. trustedNodes = "trusted-nodes.json" // Path within <datadir> to search for the trusted node list
  70. )
  71. type Config struct {
  72. DevMode bool
  73. TestNet bool
  74. Name string
  75. NetworkId int
  76. GenesisNonce int
  77. GenesisFile string
  78. GenesisBlock *types.Block // used by block tests
  79. Olympic bool
  80. BlockChainVersion int
  81. SkipBcVersionCheck bool // e.g. blockchain export
  82. DatabaseCache int
  83. DataDir string
  84. LogFile string
  85. Verbosity int
  86. LogJSON string
  87. VmDebug bool
  88. NatSpec bool
  89. AutoDAG bool
  90. PowTest bool
  91. ExtraData []byte
  92. MaxPeers int
  93. MaxPendingPeers int
  94. Discovery bool
  95. Port string
  96. // Space-separated list of discovery node URLs
  97. BootNodes string
  98. // This key is used to identify the node on the network.
  99. // If nil, an ephemeral key is used.
  100. NodeKey *ecdsa.PrivateKey
  101. NAT nat.Interface
  102. Shh bool
  103. Dial bool
  104. Etherbase common.Address
  105. GasPrice *big.Int
  106. MinerThreads int
  107. AccountManager *accounts.Manager
  108. SolcPath string
  109. GpoMinGasPrice *big.Int
  110. GpoMaxGasPrice *big.Int
  111. GpoFullBlockRatio int
  112. GpobaseStepDown int
  113. GpobaseStepUp int
  114. GpobaseCorrectionFactor int
  115. // NewDB is used to create databases.
  116. // If nil, the default is to create leveldb databases on disk.
  117. NewDB func(path string) (ethdb.Database, error)
  118. }
  119. func (cfg *Config) parseBootNodes() []*discover.Node {
  120. if cfg.BootNodes == "" {
  121. if cfg.TestNet {
  122. return defaultTestNetBootNodes
  123. }
  124. return defaultBootNodes
  125. }
  126. var ns []*discover.Node
  127. for _, url := range strings.Split(cfg.BootNodes, " ") {
  128. if url == "" {
  129. continue
  130. }
  131. n, err := discover.ParseNode(url)
  132. if err != nil {
  133. glog.V(logger.Error).Infof("Bootstrap URL %s: %v\n", url, err)
  134. continue
  135. }
  136. ns = append(ns, n)
  137. }
  138. return ns
  139. }
  140. // parseNodes parses a list of discovery node URLs loaded from a .json file.
  141. func (cfg *Config) parseNodes(file string) []*discover.Node {
  142. // Short circuit if no node config is present
  143. path := filepath.Join(cfg.DataDir, file)
  144. if _, err := os.Stat(path); err != nil {
  145. return nil
  146. }
  147. // Load the nodes from the config file
  148. blob, err := ioutil.ReadFile(path)
  149. if err != nil {
  150. glog.V(logger.Error).Infof("Failed to access nodes: %v", err)
  151. return nil
  152. }
  153. nodelist := []string{}
  154. if err := json.Unmarshal(blob, &nodelist); err != nil {
  155. glog.V(logger.Error).Infof("Failed to load nodes: %v", err)
  156. return nil
  157. }
  158. // Interpret the list as a discovery node array
  159. var nodes []*discover.Node
  160. for _, url := range nodelist {
  161. if url == "" {
  162. continue
  163. }
  164. node, err := discover.ParseNode(url)
  165. if err != nil {
  166. glog.V(logger.Error).Infof("Node URL %s: %v\n", url, err)
  167. continue
  168. }
  169. nodes = append(nodes, node)
  170. }
  171. return nodes
  172. }
  173. func (cfg *Config) nodeKey() (*ecdsa.PrivateKey, error) {
  174. // use explicit key from command line args if set
  175. if cfg.NodeKey != nil {
  176. return cfg.NodeKey, nil
  177. }
  178. // use persistent key if present
  179. keyfile := filepath.Join(cfg.DataDir, "nodekey")
  180. key, err := crypto.LoadECDSA(keyfile)
  181. if err == nil {
  182. return key, nil
  183. }
  184. // no persistent key, generate and store a new one
  185. if key, err = crypto.GenerateKey(); err != nil {
  186. return nil, fmt.Errorf("could not generate server key: %v", err)
  187. }
  188. if err := crypto.SaveECDSA(keyfile, key); err != nil {
  189. glog.V(logger.Error).Infoln("could not persist nodekey: ", err)
  190. }
  191. return key, nil
  192. }
  193. type Ethereum struct {
  194. // Channel for shutting down the ethereum
  195. shutdownChan chan bool
  196. // DB interfaces
  197. chainDb ethdb.Database // Block chain database
  198. dappDb ethdb.Database // Dapp database
  199. //*** SERVICES ***
  200. // State manager for processing new blocks and managing the over all states
  201. blockProcessor *core.BlockProcessor
  202. txPool *core.TxPool
  203. blockchain *core.BlockChain
  204. accountManager *accounts.Manager
  205. whisper *whisper.Whisper
  206. pow *ethash.Ethash
  207. protocolManager *ProtocolManager
  208. SolcPath string
  209. solc *compiler.Solidity
  210. GpoMinGasPrice *big.Int
  211. GpoMaxGasPrice *big.Int
  212. GpoFullBlockRatio int
  213. GpobaseStepDown int
  214. GpobaseStepUp int
  215. GpobaseCorrectionFactor int
  216. net *p2p.Server
  217. eventMux *event.TypeMux
  218. miner *miner.Miner
  219. // logger logger.LogSystem
  220. Mining bool
  221. MinerThreads int
  222. NatSpec bool
  223. DataDir string
  224. AutoDAG bool
  225. PowTest bool
  226. autodagquit chan bool
  227. etherbase common.Address
  228. clientVersion string
  229. netVersionId int
  230. shhVersionId int
  231. }
  232. func New(config *Config) (*Ethereum, error) {
  233. // Bootstrap database
  234. logger.New(config.DataDir, config.LogFile, config.Verbosity)
  235. if len(config.LogJSON) > 0 {
  236. logger.NewJSONsystem(config.DataDir, config.LogJSON)
  237. }
  238. // Let the database take 3/4 of the max open files (TODO figure out a way to get the actual limit of the open files)
  239. const dbCount = 3
  240. ethdb.OpenFileLimit = 128 / (dbCount + 1)
  241. newdb := config.NewDB
  242. if newdb == nil {
  243. newdb = func(path string) (ethdb.Database, error) { return ethdb.NewLDBDatabase(path, config.DatabaseCache) }
  244. }
  245. // Open the chain database and perform any upgrades needed
  246. chainDb, err := newdb(filepath.Join(config.DataDir, "chaindata"))
  247. if err != nil {
  248. return nil, fmt.Errorf("blockchain db err: %v", err)
  249. }
  250. if db, ok := chainDb.(*ethdb.LDBDatabase); ok {
  251. db.Meter("eth/db/chaindata/")
  252. }
  253. if err := upgradeChainDatabase(chainDb); err != nil {
  254. return nil, err
  255. }
  256. dappDb, err := newdb(filepath.Join(config.DataDir, "dapp"))
  257. if err != nil {
  258. return nil, fmt.Errorf("dapp db err: %v", err)
  259. }
  260. if db, ok := dappDb.(*ethdb.LDBDatabase); ok {
  261. db.Meter("eth/db/dapp/")
  262. }
  263. nodeDb := filepath.Join(config.DataDir, "nodes")
  264. glog.V(logger.Info).Infof("Protocol Versions: %v, Network Id: %v", ProtocolVersions, config.NetworkId)
  265. if len(config.GenesisFile) > 0 {
  266. fr, err := os.Open(config.GenesisFile)
  267. if err != nil {
  268. return nil, err
  269. }
  270. block, err := core.WriteGenesisBlock(chainDb, fr)
  271. if err != nil {
  272. return nil, err
  273. }
  274. glog.V(logger.Info).Infof("Successfully wrote genesis block. New genesis hash = %x\n", block.Hash())
  275. }
  276. // different modes
  277. switch {
  278. case config.Olympic:
  279. glog.V(logger.Error).Infoln("Starting Olympic network")
  280. fallthrough
  281. case config.DevMode:
  282. _, err := core.WriteOlympicGenesisBlock(chainDb, 42)
  283. if err != nil {
  284. return nil, err
  285. }
  286. case config.TestNet:
  287. state.StartingNonce = 1048576 // (2**20)
  288. _, err := core.WriteTestNetGenesisBlock(chainDb, 0x6d6f7264656e)
  289. if err != nil {
  290. return nil, err
  291. }
  292. }
  293. // This is for testing only.
  294. if config.GenesisBlock != nil {
  295. core.WriteTd(chainDb, config.GenesisBlock.Hash(), config.GenesisBlock.Difficulty())
  296. core.WriteBlock(chainDb, config.GenesisBlock)
  297. core.WriteCanonicalHash(chainDb, config.GenesisBlock.Hash(), config.GenesisBlock.NumberU64())
  298. core.WriteHeadBlockHash(chainDb, config.GenesisBlock.Hash())
  299. }
  300. if !config.SkipBcVersionCheck {
  301. b, _ := chainDb.Get([]byte("BlockchainVersion"))
  302. bcVersion := int(common.NewValue(b).Uint())
  303. if bcVersion != config.BlockChainVersion && bcVersion != 0 {
  304. return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d). Run geth upgradedb.\n", bcVersion, config.BlockChainVersion)
  305. }
  306. saveBlockchainVersion(chainDb, config.BlockChainVersion)
  307. }
  308. glog.V(logger.Info).Infof("Blockchain DB Version: %d", config.BlockChainVersion)
  309. eth := &Ethereum{
  310. shutdownChan: make(chan bool),
  311. chainDb: chainDb,
  312. dappDb: dappDb,
  313. eventMux: &event.TypeMux{},
  314. accountManager: config.AccountManager,
  315. DataDir: config.DataDir,
  316. etherbase: config.Etherbase,
  317. clientVersion: config.Name, // TODO should separate from Name
  318. netVersionId: config.NetworkId,
  319. NatSpec: config.NatSpec,
  320. MinerThreads: config.MinerThreads,
  321. SolcPath: config.SolcPath,
  322. AutoDAG: config.AutoDAG,
  323. PowTest: config.PowTest,
  324. GpoMinGasPrice: config.GpoMinGasPrice,
  325. GpoMaxGasPrice: config.GpoMaxGasPrice,
  326. GpoFullBlockRatio: config.GpoFullBlockRatio,
  327. GpobaseStepDown: config.GpobaseStepDown,
  328. GpobaseStepUp: config.GpobaseStepUp,
  329. GpobaseCorrectionFactor: config.GpobaseCorrectionFactor,
  330. }
  331. if config.PowTest {
  332. glog.V(logger.Info).Infof("ethash used in test mode")
  333. eth.pow, err = ethash.NewForTesting()
  334. if err != nil {
  335. return nil, err
  336. }
  337. } else {
  338. eth.pow = ethash.New()
  339. }
  340. //genesis := core.GenesisBlock(uint64(config.GenesisNonce), stateDb)
  341. eth.blockchain, err = core.NewBlockChain(chainDb, eth.pow, eth.EventMux())
  342. if err != nil {
  343. if err == core.ErrNoGenesis {
  344. return nil, fmt.Errorf(`Genesis block not found. Please supply a genesis block with the "--genesis /path/to/file" argument`)
  345. }
  346. return nil, err
  347. }
  348. newPool := core.NewTxPool(eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
  349. eth.txPool = newPool
  350. eth.blockProcessor = core.NewBlockProcessor(chainDb, eth.pow, eth.blockchain, eth.EventMux())
  351. eth.blockchain.SetProcessor(eth.blockProcessor)
  352. eth.protocolManager = NewProtocolManager(config.NetworkId, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb)
  353. eth.miner = miner.New(eth, eth.EventMux(), eth.pow)
  354. eth.miner.SetGasPrice(config.GasPrice)
  355. eth.miner.SetExtra(config.ExtraData)
  356. if config.Shh {
  357. eth.whisper = whisper.New()
  358. eth.shhVersionId = int(eth.whisper.Version())
  359. }
  360. netprv, err := config.nodeKey()
  361. if err != nil {
  362. return nil, err
  363. }
  364. protocols := append([]p2p.Protocol{}, eth.protocolManager.SubProtocols...)
  365. if config.Shh {
  366. protocols = append(protocols, eth.whisper.Protocol())
  367. }
  368. eth.net = &p2p.Server{
  369. PrivateKey: netprv,
  370. Name: config.Name,
  371. MaxPeers: config.MaxPeers,
  372. MaxPendingPeers: config.MaxPendingPeers,
  373. Discovery: config.Discovery,
  374. Protocols: protocols,
  375. NAT: config.NAT,
  376. NoDial: !config.Dial,
  377. BootstrapNodes: config.parseBootNodes(),
  378. StaticNodes: config.parseNodes(staticNodes),
  379. TrustedNodes: config.parseNodes(trustedNodes),
  380. NodeDatabase: nodeDb,
  381. }
  382. if len(config.Port) > 0 {
  383. eth.net.ListenAddr = ":" + config.Port
  384. }
  385. vm.Debug = config.VmDebug
  386. return eth, nil
  387. }
  388. type NodeInfo struct {
  389. Name string
  390. NodeUrl string
  391. NodeID string
  392. IP string
  393. DiscPort int // UDP listening port for discovery protocol
  394. TCPPort int // TCP listening port for RLPx
  395. Td string
  396. ListenAddr string
  397. }
  398. func (s *Ethereum) NodeInfo() *NodeInfo {
  399. node := s.net.Self()
  400. return &NodeInfo{
  401. Name: s.Name(),
  402. NodeUrl: node.String(),
  403. NodeID: node.ID.String(),
  404. IP: node.IP.String(),
  405. DiscPort: int(node.UDP),
  406. TCPPort: int(node.TCP),
  407. ListenAddr: s.net.ListenAddr,
  408. Td: s.BlockChain().Td().String(),
  409. }
  410. }
  411. type PeerInfo struct {
  412. ID string
  413. Name string
  414. Caps string
  415. RemoteAddress string
  416. LocalAddress string
  417. }
  418. func newPeerInfo(peer *p2p.Peer) *PeerInfo {
  419. var caps []string
  420. for _, cap := range peer.Caps() {
  421. caps = append(caps, cap.String())
  422. }
  423. return &PeerInfo{
  424. ID: peer.ID().String(),
  425. Name: peer.Name(),
  426. Caps: strings.Join(caps, ", "),
  427. RemoteAddress: peer.RemoteAddr().String(),
  428. LocalAddress: peer.LocalAddr().String(),
  429. }
  430. }
  431. // PeersInfo returns an array of PeerInfo objects describing connected peers
  432. func (s *Ethereum) PeersInfo() (peersinfo []*PeerInfo) {
  433. for _, peer := range s.net.Peers() {
  434. if peer != nil {
  435. peersinfo = append(peersinfo, newPeerInfo(peer))
  436. }
  437. }
  438. return
  439. }
  440. func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
  441. s.blockchain.ResetWithGenesisBlock(gb)
  442. }
  443. func (s *Ethereum) StartMining(threads int) error {
  444. eb, err := s.Etherbase()
  445. if err != nil {
  446. err = fmt.Errorf("Cannot start mining without etherbase address: %v", err)
  447. glog.V(logger.Error).Infoln(err)
  448. return err
  449. }
  450. go s.miner.Start(eb, threads)
  451. return nil
  452. }
  453. func (s *Ethereum) Etherbase() (eb common.Address, err error) {
  454. eb = s.etherbase
  455. if (eb == common.Address{}) {
  456. addr, e := s.AccountManager().AddressByIndex(0)
  457. if e != nil {
  458. err = fmt.Errorf("etherbase address must be explicitly specified")
  459. }
  460. eb = common.HexToAddress(addr)
  461. }
  462. return
  463. }
  464. // set in js console via admin interface or wrapper from cli flags
  465. func (self *Ethereum) SetEtherbase(etherbase common.Address) {
  466. self.etherbase = etherbase
  467. self.miner.SetEtherbase(etherbase)
  468. }
  469. func (s *Ethereum) StopMining() { s.miner.Stop() }
  470. func (s *Ethereum) IsMining() bool { return s.miner.Mining() }
  471. func (s *Ethereum) Miner() *miner.Miner { return s.miner }
  472. // func (s *Ethereum) Logger() logger.LogSystem { return s.logger }
  473. func (s *Ethereum) Name() string { return s.net.Name }
  474. func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }
  475. func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
  476. func (s *Ethereum) BlockProcessor() *core.BlockProcessor { return s.blockProcessor }
  477. func (s *Ethereum) TxPool() *core.TxPool { return s.txPool }
  478. func (s *Ethereum) Whisper() *whisper.Whisper { return s.whisper }
  479. func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
  480. func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb }
  481. func (s *Ethereum) DappDb() ethdb.Database { return s.dappDb }
  482. func (s *Ethereum) IsListening() bool { return true } // Always listening
  483. func (s *Ethereum) PeerCount() int { return s.net.PeerCount() }
  484. func (s *Ethereum) Peers() []*p2p.Peer { return s.net.Peers() }
  485. func (s *Ethereum) MaxPeers() int { return s.net.MaxPeers }
  486. func (s *Ethereum) ClientVersion() string { return s.clientVersion }
  487. func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) }
  488. func (s *Ethereum) NetVersion() int { return s.netVersionId }
  489. func (s *Ethereum) ShhVersion() int { return s.shhVersionId }
  490. func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader }
  491. // Start the ethereum
  492. func (s *Ethereum) Start() error {
  493. jsonlogger.LogJson(&logger.LogStarting{
  494. ClientString: s.net.Name,
  495. ProtocolVersion: s.EthVersion(),
  496. })
  497. err := s.net.Start()
  498. if err != nil {
  499. return err
  500. }
  501. if s.AutoDAG {
  502. s.StartAutoDAG()
  503. }
  504. s.protocolManager.Start()
  505. if s.whisper != nil {
  506. s.whisper.Start()
  507. }
  508. glog.V(logger.Info).Infoln("Server started")
  509. return nil
  510. }
  511. func (s *Ethereum) StartForTest() {
  512. jsonlogger.LogJson(&logger.LogStarting{
  513. ClientString: s.net.Name,
  514. ProtocolVersion: s.EthVersion(),
  515. })
  516. }
  517. // AddPeer connects to the given node and maintains the connection until the
  518. // server is shut down. If the connection fails for any reason, the server will
  519. // attempt to reconnect the peer.
  520. func (self *Ethereum) AddPeer(nodeURL string) error {
  521. n, err := discover.ParseNode(nodeURL)
  522. if err != nil {
  523. return fmt.Errorf("invalid node URL: %v", err)
  524. }
  525. self.net.AddPeer(n)
  526. return nil
  527. }
  528. func (s *Ethereum) Stop() {
  529. s.net.Stop()
  530. s.blockchain.Stop()
  531. s.protocolManager.Stop()
  532. s.txPool.Stop()
  533. s.eventMux.Stop()
  534. if s.whisper != nil {
  535. s.whisper.Stop()
  536. }
  537. s.StopAutoDAG()
  538. s.chainDb.Close()
  539. s.dappDb.Close()
  540. close(s.shutdownChan)
  541. }
  542. // This function will wait for a shutdown and resumes main thread execution
  543. func (s *Ethereum) WaitForShutdown() {
  544. <-s.shutdownChan
  545. }
  546. // StartAutoDAG() spawns a go routine that checks the DAG every autoDAGcheckInterval
  547. // by default that is 10 times per epoch
  548. // in epoch n, if we past autoDAGepochHeight within-epoch blocks,
  549. // it calls ethash.MakeDAG to pregenerate the DAG for the next epoch n+1
  550. // if it does not exist yet as well as remove the DAG for epoch n-1
  551. // the loop quits if autodagquit channel is closed, it can safely restart and
  552. // stop any number of times.
  553. // For any more sophisticated pattern of DAG generation, use CLI subcommand
  554. // makedag
  555. func (self *Ethereum) StartAutoDAG() {
  556. if self.autodagquit != nil {
  557. return // already started
  558. }
  559. go func() {
  560. glog.V(logger.Info).Infof("Automatic pregeneration of ethash DAG ON (ethash dir: %s)", ethash.DefaultDir)
  561. var nextEpoch uint64
  562. timer := time.After(0)
  563. self.autodagquit = make(chan bool)
  564. for {
  565. select {
  566. case <-timer:
  567. glog.V(logger.Info).Infof("checking DAG (ethash dir: %s)", ethash.DefaultDir)
  568. currentBlock := self.BlockChain().CurrentBlock().NumberU64()
  569. thisEpoch := currentBlock / epochLength
  570. if nextEpoch <= thisEpoch {
  571. if currentBlock%epochLength > autoDAGepochHeight {
  572. if thisEpoch > 0 {
  573. previousDag, previousDagFull := dagFiles(thisEpoch - 1)
  574. os.Remove(filepath.Join(ethash.DefaultDir, previousDag))
  575. os.Remove(filepath.Join(ethash.DefaultDir, previousDagFull))
  576. glog.V(logger.Info).Infof("removed DAG for epoch %d (%s)", thisEpoch-1, previousDag)
  577. }
  578. nextEpoch = thisEpoch + 1
  579. dag, _ := dagFiles(nextEpoch)
  580. if _, err := os.Stat(dag); os.IsNotExist(err) {
  581. glog.V(logger.Info).Infof("Pregenerating DAG for epoch %d (%s)", nextEpoch, dag)
  582. err := ethash.MakeDAG(nextEpoch*epochLength, "") // "" -> ethash.DefaultDir
  583. if err != nil {
  584. glog.V(logger.Error).Infof("Error generating DAG for epoch %d (%s)", nextEpoch, dag)
  585. return
  586. }
  587. } else {
  588. glog.V(logger.Error).Infof("DAG for epoch %d (%s)", nextEpoch, dag)
  589. }
  590. }
  591. }
  592. timer = time.After(autoDAGcheckInterval)
  593. case <-self.autodagquit:
  594. return
  595. }
  596. }
  597. }()
  598. }
  599. // stopAutoDAG stops automatic DAG pregeneration by quitting the loop
  600. func (self *Ethereum) StopAutoDAG() {
  601. if self.autodagquit != nil {
  602. close(self.autodagquit)
  603. self.autodagquit = nil
  604. }
  605. glog.V(logger.Info).Infof("Automatic pregeneration of ethash DAG OFF (ethash dir: %s)", ethash.DefaultDir)
  606. }
  607. func (self *Ethereum) Solc() (*compiler.Solidity, error) {
  608. var err error
  609. if self.solc == nil {
  610. self.solc, err = compiler.New(self.SolcPath)
  611. }
  612. return self.solc, err
  613. }
  614. // set in js console via admin interface or wrapper from cli flags
  615. func (self *Ethereum) SetSolc(solcPath string) (*compiler.Solidity, error) {
  616. self.SolcPath = solcPath
  617. self.solc = nil
  618. return self.Solc()
  619. }
  620. // dagFiles(epoch) returns the two alternative DAG filenames (not a path)
  621. // 1) <revision>-<hex(seedhash[8])> 2) full-R<revision>-<hex(seedhash[8])>
  622. func dagFiles(epoch uint64) (string, string) {
  623. seedHash, _ := ethash.GetSeedHash(epoch * epochLength)
  624. dag := fmt.Sprintf("full-R%d-%x", ethashRevision, seedHash[:8])
  625. return dag, "full-R" + dag
  626. }
  627. func saveBlockchainVersion(db ethdb.Database, bcVersion int) {
  628. d, _ := db.Get([]byte("BlockchainVersion"))
  629. blockchainVersion := common.NewValue(d).Uint()
  630. if blockchainVersion == 0 {
  631. db.Put([]byte("BlockchainVersion"), common.NewValue(bcVersion).Bytes())
  632. }
  633. }
  634. // upgradeChainDatabase ensures that the chain database stores block split into
  635. // separate header and body entries.
  636. func upgradeChainDatabase(db ethdb.Database) error {
  637. // Short circuit if the head block is stored already as separate header and body
  638. data, err := db.Get([]byte("LastBlock"))
  639. if err != nil {
  640. return nil
  641. }
  642. head := common.BytesToHash(data)
  643. if block := core.GetBlockByHashOld(db, head); block == nil {
  644. return nil
  645. }
  646. // At least some of the database is still the old format, upgrade (skip the head block!)
  647. glog.V(logger.Info).Info("Old database detected, upgrading...")
  648. if db, ok := db.(*ethdb.LDBDatabase); ok {
  649. blockPrefix := []byte("block-hash-")
  650. for it := db.NewIterator(); it.Next(); {
  651. // Skip anything other than a combined block
  652. if !bytes.HasPrefix(it.Key(), blockPrefix) {
  653. continue
  654. }
  655. // Skip the head block (merge last to signal upgrade completion)
  656. if bytes.HasSuffix(it.Key(), head.Bytes()) {
  657. continue
  658. }
  659. // Load the block, split and serialize (order!)
  660. block := core.GetBlockByHashOld(db, common.BytesToHash(bytes.TrimPrefix(it.Key(), blockPrefix)))
  661. if err := core.WriteTd(db, block.Hash(), block.DeprecatedTd()); err != nil {
  662. return err
  663. }
  664. if err := core.WriteBody(db, block.Hash(), &types.Body{block.Transactions(), block.Uncles()}); err != nil {
  665. return err
  666. }
  667. if err := core.WriteHeader(db, block.Header()); err != nil {
  668. return err
  669. }
  670. if err := db.Delete(it.Key()); err != nil {
  671. return err
  672. }
  673. }
  674. // Lastly, upgrade the head block, disabling the upgrade mechanism
  675. current := core.GetBlockByHashOld(db, head)
  676. if err := core.WriteTd(db, current.Hash(), current.DeprecatedTd()); err != nil {
  677. return err
  678. }
  679. if err := core.WriteBody(db, current.Hash(), &types.Body{current.Transactions(), current.Uncles()}); err != nil {
  680. return err
  681. }
  682. if err := core.WriteHeader(db, current.Header()); err != nil {
  683. return err
  684. }
  685. }
  686. return nil
  687. }