backend.go 25 KB

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