backend.go 25 KB

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