backend.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  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. eth.txPool = core.NewTxPool(eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
  349. eth.blockProcessor = core.NewBlockProcessor(chainDb, eth.pow, eth.blockchain, eth.EventMux())
  350. eth.blockchain.SetProcessor(eth.blockProcessor)
  351. eth.protocolManager = NewProtocolManager(config.NetworkId, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb)
  352. eth.miner = miner.New(eth, eth.EventMux(), eth.pow)
  353. eth.miner.SetGasPrice(config.GasPrice)
  354. eth.miner.SetExtra(config.ExtraData)
  355. if config.Shh {
  356. eth.whisper = whisper.New()
  357. eth.shhVersionId = int(eth.whisper.Version())
  358. }
  359. netprv, err := config.nodeKey()
  360. if err != nil {
  361. return nil, err
  362. }
  363. protocols := append([]p2p.Protocol{}, eth.protocolManager.SubProtocols...)
  364. if config.Shh {
  365. protocols = append(protocols, eth.whisper.Protocol())
  366. }
  367. eth.net = &p2p.Server{
  368. PrivateKey: netprv,
  369. Name: config.Name,
  370. MaxPeers: config.MaxPeers,
  371. MaxPendingPeers: config.MaxPendingPeers,
  372. Discovery: config.Discovery,
  373. Protocols: protocols,
  374. NAT: config.NAT,
  375. NoDial: !config.Dial,
  376. BootstrapNodes: config.parseBootNodes(),
  377. StaticNodes: config.parseNodes(staticNodes),
  378. TrustedNodes: config.parseNodes(trustedNodes),
  379. NodeDatabase: nodeDb,
  380. }
  381. if len(config.Port) > 0 {
  382. eth.net.ListenAddr = ":" + config.Port
  383. }
  384. vm.Debug = config.VmDebug
  385. return eth, nil
  386. }
  387. type NodeInfo struct {
  388. Name string
  389. NodeUrl string
  390. NodeID string
  391. IP string
  392. DiscPort int // UDP listening port for discovery protocol
  393. TCPPort int // TCP listening port for RLPx
  394. Td string
  395. ListenAddr string
  396. }
  397. func (s *Ethereum) NodeInfo() *NodeInfo {
  398. node := s.net.Self()
  399. return &NodeInfo{
  400. Name: s.Name(),
  401. NodeUrl: node.String(),
  402. NodeID: node.ID.String(),
  403. IP: node.IP.String(),
  404. DiscPort: int(node.UDP),
  405. TCPPort: int(node.TCP),
  406. ListenAddr: s.net.ListenAddr,
  407. Td: s.BlockChain().Td().String(),
  408. }
  409. }
  410. type PeerInfo struct {
  411. ID string
  412. Name string
  413. Caps string
  414. RemoteAddress string
  415. LocalAddress string
  416. }
  417. func newPeerInfo(peer *p2p.Peer) *PeerInfo {
  418. var caps []string
  419. for _, cap := range peer.Caps() {
  420. caps = append(caps, cap.String())
  421. }
  422. return &PeerInfo{
  423. ID: peer.ID().String(),
  424. Name: peer.Name(),
  425. Caps: strings.Join(caps, ", "),
  426. RemoteAddress: peer.RemoteAddr().String(),
  427. LocalAddress: peer.LocalAddr().String(),
  428. }
  429. }
  430. // PeersInfo returns an array of PeerInfo objects describing connected peers
  431. func (s *Ethereum) PeersInfo() (peersinfo []*PeerInfo) {
  432. for _, peer := range s.net.Peers() {
  433. if peer != nil {
  434. peersinfo = append(peersinfo, newPeerInfo(peer))
  435. }
  436. }
  437. return
  438. }
  439. func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
  440. s.blockchain.ResetWithGenesisBlock(gb)
  441. }
  442. func (s *Ethereum) StartMining(threads int) error {
  443. eb, err := s.Etherbase()
  444. if err != nil {
  445. err = fmt.Errorf("Cannot start mining without etherbase address: %v", err)
  446. glog.V(logger.Error).Infoln(err)
  447. return err
  448. }
  449. go s.miner.Start(eb, threads)
  450. return nil
  451. }
  452. func (s *Ethereum) Etherbase() (eb common.Address, err error) {
  453. eb = s.etherbase
  454. if (eb == common.Address{}) {
  455. addr, e := s.AccountManager().AddressByIndex(0)
  456. if e != nil {
  457. err = fmt.Errorf("etherbase address must be explicitly specified")
  458. }
  459. eb = common.HexToAddress(addr)
  460. }
  461. return
  462. }
  463. // set in js console via admin interface or wrapper from cli flags
  464. func (self *Ethereum) SetEtherbase(etherbase common.Address) {
  465. self.etherbase = etherbase
  466. self.miner.SetEtherbase(etherbase)
  467. }
  468. func (s *Ethereum) StopMining() { s.miner.Stop() }
  469. func (s *Ethereum) IsMining() bool { return s.miner.Mining() }
  470. func (s *Ethereum) Miner() *miner.Miner { return s.miner }
  471. // func (s *Ethereum) Logger() logger.LogSystem { return s.logger }
  472. func (s *Ethereum) Name() string { return s.net.Name }
  473. func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }
  474. func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
  475. func (s *Ethereum) BlockProcessor() *core.BlockProcessor { return s.blockProcessor }
  476. func (s *Ethereum) TxPool() *core.TxPool { return s.txPool }
  477. func (s *Ethereum) Whisper() *whisper.Whisper { return s.whisper }
  478. func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
  479. func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb }
  480. func (s *Ethereum) DappDb() ethdb.Database { return s.dappDb }
  481. func (s *Ethereum) IsListening() bool { return true } // Always listening
  482. func (s *Ethereum) PeerCount() int { return s.net.PeerCount() }
  483. func (s *Ethereum) Peers() []*p2p.Peer { return s.net.Peers() }
  484. func (s *Ethereum) MaxPeers() int { return s.net.MaxPeers }
  485. func (s *Ethereum) ClientVersion() string { return s.clientVersion }
  486. func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) }
  487. func (s *Ethereum) NetVersion() int { return s.netVersionId }
  488. func (s *Ethereum) ShhVersion() int { return s.shhVersionId }
  489. func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader }
  490. // Start the ethereum
  491. func (s *Ethereum) Start() error {
  492. jsonlogger.LogJson(&logger.LogStarting{
  493. ClientString: s.net.Name,
  494. ProtocolVersion: s.EthVersion(),
  495. })
  496. err := s.net.Start()
  497. if err != nil {
  498. return err
  499. }
  500. if s.AutoDAG {
  501. s.StartAutoDAG()
  502. }
  503. s.protocolManager.Start()
  504. if s.whisper != nil {
  505. s.whisper.Start()
  506. }
  507. glog.V(logger.Info).Infoln("Server started")
  508. return nil
  509. }
  510. func (s *Ethereum) StartForTest() {
  511. jsonlogger.LogJson(&logger.LogStarting{
  512. ClientString: s.net.Name,
  513. ProtocolVersion: s.EthVersion(),
  514. })
  515. }
  516. // AddPeer connects to the given node and maintains the connection until the
  517. // server is shut down. If the connection fails for any reason, the server will
  518. // attempt to reconnect the peer.
  519. func (self *Ethereum) AddPeer(nodeURL string) error {
  520. n, err := discover.ParseNode(nodeURL)
  521. if err != nil {
  522. return fmt.Errorf("invalid node URL: %v", err)
  523. }
  524. self.net.AddPeer(n)
  525. return nil
  526. }
  527. func (s *Ethereum) Stop() {
  528. s.net.Stop()
  529. s.blockchain.Stop()
  530. s.protocolManager.Stop()
  531. s.txPool.Stop()
  532. s.eventMux.Stop()
  533. if s.whisper != nil {
  534. s.whisper.Stop()
  535. }
  536. s.StopAutoDAG()
  537. s.chainDb.Close()
  538. s.dappDb.Close()
  539. close(s.shutdownChan)
  540. }
  541. // This function will wait for a shutdown and resumes main thread execution
  542. func (s *Ethereum) WaitForShutdown() {
  543. <-s.shutdownChan
  544. }
  545. // StartAutoDAG() spawns a go routine that checks the DAG every autoDAGcheckInterval
  546. // by default that is 10 times per epoch
  547. // in epoch n, if we past autoDAGepochHeight within-epoch blocks,
  548. // it calls ethash.MakeDAG to pregenerate the DAG for the next epoch n+1
  549. // if it does not exist yet as well as remove the DAG for epoch n-1
  550. // the loop quits if autodagquit channel is closed, it can safely restart and
  551. // stop any number of times.
  552. // For any more sophisticated pattern of DAG generation, use CLI subcommand
  553. // makedag
  554. func (self *Ethereum) StartAutoDAG() {
  555. if self.autodagquit != nil {
  556. return // already started
  557. }
  558. go func() {
  559. glog.V(logger.Info).Infof("Automatic pregeneration of ethash DAG ON (ethash dir: %s)", ethash.DefaultDir)
  560. var nextEpoch uint64
  561. timer := time.After(0)
  562. self.autodagquit = make(chan bool)
  563. for {
  564. select {
  565. case <-timer:
  566. glog.V(logger.Info).Infof("checking DAG (ethash dir: %s)", ethash.DefaultDir)
  567. currentBlock := self.BlockChain().CurrentBlock().NumberU64()
  568. thisEpoch := currentBlock / epochLength
  569. if nextEpoch <= thisEpoch {
  570. if currentBlock%epochLength > autoDAGepochHeight {
  571. if thisEpoch > 0 {
  572. previousDag, previousDagFull := dagFiles(thisEpoch - 1)
  573. os.Remove(filepath.Join(ethash.DefaultDir, previousDag))
  574. os.Remove(filepath.Join(ethash.DefaultDir, previousDagFull))
  575. glog.V(logger.Info).Infof("removed DAG for epoch %d (%s)", thisEpoch-1, previousDag)
  576. }
  577. nextEpoch = thisEpoch + 1
  578. dag, _ := dagFiles(nextEpoch)
  579. if _, err := os.Stat(dag); os.IsNotExist(err) {
  580. glog.V(logger.Info).Infof("Pregenerating DAG for epoch %d (%s)", nextEpoch, dag)
  581. err := ethash.MakeDAG(nextEpoch*epochLength, "") // "" -> ethash.DefaultDir
  582. if err != nil {
  583. glog.V(logger.Error).Infof("Error generating DAG for epoch %d (%s)", nextEpoch, dag)
  584. return
  585. }
  586. } else {
  587. glog.V(logger.Error).Infof("DAG for epoch %d (%s)", nextEpoch, dag)
  588. }
  589. }
  590. }
  591. timer = time.After(autoDAGcheckInterval)
  592. case <-self.autodagquit:
  593. return
  594. }
  595. }
  596. }()
  597. }
  598. // stopAutoDAG stops automatic DAG pregeneration by quitting the loop
  599. func (self *Ethereum) StopAutoDAG() {
  600. if self.autodagquit != nil {
  601. close(self.autodagquit)
  602. self.autodagquit = nil
  603. }
  604. glog.V(logger.Info).Infof("Automatic pregeneration of ethash DAG OFF (ethash dir: %s)", ethash.DefaultDir)
  605. }
  606. func (self *Ethereum) Solc() (*compiler.Solidity, error) {
  607. var err error
  608. if self.solc == nil {
  609. self.solc, err = compiler.New(self.SolcPath)
  610. }
  611. return self.solc, err
  612. }
  613. // set in js console via admin interface or wrapper from cli flags
  614. func (self *Ethereum) SetSolc(solcPath string) (*compiler.Solidity, error) {
  615. self.SolcPath = solcPath
  616. self.solc = nil
  617. return self.Solc()
  618. }
  619. // dagFiles(epoch) returns the two alternative DAG filenames (not a path)
  620. // 1) <revision>-<hex(seedhash[8])> 2) full-R<revision>-<hex(seedhash[8])>
  621. func dagFiles(epoch uint64) (string, string) {
  622. seedHash, _ := ethash.GetSeedHash(epoch * epochLength)
  623. dag := fmt.Sprintf("full-R%d-%x", ethashRevision, seedHash[:8])
  624. return dag, "full-R" + dag
  625. }
  626. func saveBlockchainVersion(db ethdb.Database, bcVersion int) {
  627. d, _ := db.Get([]byte("BlockchainVersion"))
  628. blockchainVersion := common.NewValue(d).Uint()
  629. if blockchainVersion == 0 {
  630. db.Put([]byte("BlockchainVersion"), common.NewValue(bcVersion).Bytes())
  631. }
  632. }
  633. // upgradeChainDatabase ensures that the chain database stores block split into
  634. // separate header and body entries.
  635. func upgradeChainDatabase(db ethdb.Database) error {
  636. // Short circuit if the head block is stored already as separate header and body
  637. data, err := db.Get([]byte("LastBlock"))
  638. if err != nil {
  639. return nil
  640. }
  641. head := common.BytesToHash(data)
  642. if block := core.GetBlockByHashOld(db, head); block == nil {
  643. return nil
  644. }
  645. // At least some of the database is still the old format, upgrade (skip the head block!)
  646. glog.V(logger.Info).Info("Old database detected, upgrading...")
  647. if db, ok := db.(*ethdb.LDBDatabase); ok {
  648. blockPrefix := []byte("block-hash-")
  649. for it := db.NewIterator(); it.Next(); {
  650. // Skip anything other than a combined block
  651. if !bytes.HasPrefix(it.Key(), blockPrefix) {
  652. continue
  653. }
  654. // Skip the head block (merge last to signal upgrade completion)
  655. if bytes.HasSuffix(it.Key(), head.Bytes()) {
  656. continue
  657. }
  658. // Load the block, split and serialize (order!)
  659. block := core.GetBlockByHashOld(db, common.BytesToHash(bytes.TrimPrefix(it.Key(), blockPrefix)))
  660. if err := core.WriteTd(db, block.Hash(), block.DeprecatedTd()); err != nil {
  661. return err
  662. }
  663. if err := core.WriteBody(db, block.Hash(), &types.Body{block.Transactions(), block.Uncles()}); err != nil {
  664. return err
  665. }
  666. if err := core.WriteHeader(db, block.Header()); err != nil {
  667. return err
  668. }
  669. if err := db.Delete(it.Key()); err != nil {
  670. return err
  671. }
  672. }
  673. // Lastly, upgrade the head block, disabling the upgrade mechanism
  674. current := core.GetBlockByHashOld(db, head)
  675. if err := core.WriteTd(db, current.Hash(), current.DeprecatedTd()); err != nil {
  676. return err
  677. }
  678. if err := core.WriteBody(db, current.Hash(), &types.Body{current.Transactions(), current.Uncles()}); err != nil {
  679. return err
  680. }
  681. if err := core.WriteHeader(db, current.Header()); err != nil {
  682. return err
  683. }
  684. }
  685. return nil
  686. }