backend.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. package eth
  2. import (
  3. "crypto/ecdsa"
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "math/big"
  8. "os"
  9. "path/filepath"
  10. "strings"
  11. "time"
  12. "github.com/ethereum/ethash"
  13. "github.com/ethereum/go-ethereum/accounts"
  14. "github.com/ethereum/go-ethereum/common"
  15. "github.com/ethereum/go-ethereum/common/compiler"
  16. "github.com/ethereum/go-ethereum/core"
  17. "github.com/ethereum/go-ethereum/core/types"
  18. "github.com/ethereum/go-ethereum/core/vm"
  19. "github.com/ethereum/go-ethereum/crypto"
  20. "github.com/ethereum/go-ethereum/eth/downloader"
  21. "github.com/ethereum/go-ethereum/ethdb"
  22. "github.com/ethereum/go-ethereum/event"
  23. "github.com/ethereum/go-ethereum/logger"
  24. "github.com/ethereum/go-ethereum/logger/glog"
  25. "github.com/ethereum/go-ethereum/miner"
  26. "github.com/ethereum/go-ethereum/p2p"
  27. "github.com/ethereum/go-ethereum/p2p/discover"
  28. "github.com/ethereum/go-ethereum/p2p/nat"
  29. "github.com/ethereum/go-ethereum/whisper"
  30. )
  31. const (
  32. epochLength = 30000
  33. ethashRevision = 23
  34. autoDAGcheckInterval = 10 * time.Hour
  35. autoDAGepochHeight = epochLength / 2
  36. )
  37. var (
  38. jsonlogger = logger.NewJsonLogger()
  39. defaultBootNodes = []*discover.Node{
  40. // ETH/DEV Go Bootnodes
  41. discover.MustParseNode("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303"),
  42. discover.MustParseNode("enode://de471bccee3d042261d52e9bff31458daecc406142b401d4cd848f677479f73104b9fdeb090af9583d3391b7f10cb2ba9e26865dd5fca4fcdc0fb1e3b723c786@54.94.239.50:30303"),
  43. // ETH/DEV cpp-ethereum (poc-9.ethdev.com)
  44. discover.MustParseNode("enode://487611428e6c99a11a9795a6abe7b529e81315ca6aad66e2a2fc76e3adf263faba0d35466c2f8f68d561dbefa8878d4df5f1f2ddb1fbeab7f42ffb8cd328bd4a@5.1.83.226:30303"),
  45. }
  46. staticNodes = "static-nodes.json" // Path within <datadir> to search for the static node list
  47. trustedNodes = "trusted-nodes.json" // Path within <datadir> to search for the trusted node list
  48. )
  49. type Config struct {
  50. Name string
  51. ProtocolVersion int
  52. NetworkId int
  53. GenesisNonce int
  54. BlockChainVersion int
  55. SkipBcVersionCheck bool // e.g. blockchain export
  56. DataDir string
  57. LogFile string
  58. Verbosity int
  59. LogJSON string
  60. VmDebug bool
  61. NatSpec bool
  62. AutoDAG bool
  63. MaxPeers int
  64. MaxPendingPeers int
  65. Discovery bool
  66. Port string
  67. // Space-separated list of discovery node URLs
  68. BootNodes string
  69. // This key is used to identify the node on the network.
  70. // If nil, an ephemeral key is used.
  71. NodeKey *ecdsa.PrivateKey
  72. NAT nat.Interface
  73. Shh bool
  74. Dial bool
  75. Etherbase string
  76. GasPrice *big.Int
  77. MinerThreads int
  78. AccountManager *accounts.Manager
  79. SolcPath string
  80. // NewDB is used to create databases.
  81. // If nil, the default is to create leveldb databases on disk.
  82. NewDB func(path string) (common.Database, error)
  83. }
  84. func (cfg *Config) parseBootNodes() []*discover.Node {
  85. if cfg.BootNodes == "" {
  86. return defaultBootNodes
  87. }
  88. var ns []*discover.Node
  89. for _, url := range strings.Split(cfg.BootNodes, " ") {
  90. if url == "" {
  91. continue
  92. }
  93. n, err := discover.ParseNode(url)
  94. if err != nil {
  95. glog.V(logger.Error).Infof("Bootstrap URL %s: %v\n", url, err)
  96. continue
  97. }
  98. ns = append(ns, n)
  99. }
  100. return ns
  101. }
  102. // parseNodes parses a list of discovery node URLs loaded from a .json file.
  103. func (cfg *Config) parseNodes(file string) []*discover.Node {
  104. // Short circuit if no node config is present
  105. path := filepath.Join(cfg.DataDir, file)
  106. if _, err := os.Stat(path); err != nil {
  107. return nil
  108. }
  109. // Load the nodes from the config file
  110. blob, err := ioutil.ReadFile(path)
  111. if err != nil {
  112. glog.V(logger.Error).Infof("Failed to access nodes: %v", err)
  113. return nil
  114. }
  115. nodelist := []string{}
  116. if err := json.Unmarshal(blob, &nodelist); err != nil {
  117. glog.V(logger.Error).Infof("Failed to load nodes: %v", err)
  118. return nil
  119. }
  120. // Interpret the list as a discovery node array
  121. var nodes []*discover.Node
  122. for _, url := range nodelist {
  123. if url == "" {
  124. continue
  125. }
  126. node, err := discover.ParseNode(url)
  127. if err != nil {
  128. glog.V(logger.Error).Infof("Node URL %s: %v\n", url, err)
  129. continue
  130. }
  131. nodes = append(nodes, node)
  132. }
  133. return nodes
  134. }
  135. func (cfg *Config) nodeKey() (*ecdsa.PrivateKey, error) {
  136. // use explicit key from command line args if set
  137. if cfg.NodeKey != nil {
  138. return cfg.NodeKey, nil
  139. }
  140. // use persistent key if present
  141. keyfile := filepath.Join(cfg.DataDir, "nodekey")
  142. key, err := crypto.LoadECDSA(keyfile)
  143. if err == nil {
  144. return key, nil
  145. }
  146. // no persistent key, generate and store a new one
  147. if key, err = crypto.GenerateKey(); err != nil {
  148. return nil, fmt.Errorf("could not generate server key: %v", err)
  149. }
  150. if err := crypto.SaveECDSA(keyfile, key); err != nil {
  151. glog.V(logger.Error).Infoln("could not persist nodekey: ", err)
  152. }
  153. return key, nil
  154. }
  155. type Ethereum struct {
  156. // Channel for shutting down the ethereum
  157. shutdownChan chan bool
  158. // DB interfaces
  159. blockDb common.Database // Block chain database
  160. stateDb common.Database // State changes database
  161. extraDb common.Database // Extra database (txs, etc)
  162. // Closed when databases are flushed and closed
  163. databasesClosed chan bool
  164. //*** SERVICES ***
  165. // State manager for processing new blocks and managing the over all states
  166. blockProcessor *core.BlockProcessor
  167. txPool *core.TxPool
  168. chainManager *core.ChainManager
  169. accountManager *accounts.Manager
  170. whisper *whisper.Whisper
  171. pow *ethash.Ethash
  172. protocolManager *ProtocolManager
  173. downloader *downloader.Downloader
  174. SolcPath string
  175. solc *compiler.Solidity
  176. net *p2p.Server
  177. eventMux *event.TypeMux
  178. miner *miner.Miner
  179. // logger logger.LogSystem
  180. Mining bool
  181. MinerThreads int
  182. NatSpec bool
  183. DataDir string
  184. AutoDAG bool
  185. autodagquit chan bool
  186. etherbase common.Address
  187. clientVersion string
  188. ethVersionId int
  189. netVersionId int
  190. shhVersionId int
  191. }
  192. func New(config *Config) (*Ethereum, error) {
  193. // Bootstrap database
  194. logger.New(config.DataDir, config.LogFile, config.Verbosity)
  195. if len(config.LogJSON) > 0 {
  196. logger.NewJSONsystem(config.DataDir, config.LogJSON)
  197. }
  198. // 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)
  199. const dbCount = 3
  200. ethdb.OpenFileLimit = 128 / (dbCount + 1)
  201. newdb := config.NewDB
  202. if newdb == nil {
  203. newdb = func(path string) (common.Database, error) { return ethdb.NewLDBDatabase(path) }
  204. }
  205. blockDb, err := newdb(filepath.Join(config.DataDir, "blockchain"))
  206. if err != nil {
  207. return nil, fmt.Errorf("blockchain db err: %v", err)
  208. }
  209. stateDb, err := newdb(filepath.Join(config.DataDir, "state"))
  210. if err != nil {
  211. return nil, fmt.Errorf("state db err: %v", err)
  212. }
  213. extraDb, err := newdb(filepath.Join(config.DataDir, "extra"))
  214. if err != nil {
  215. return nil, fmt.Errorf("extra db err: %v", err)
  216. }
  217. nodeDb := filepath.Join(config.DataDir, "nodes")
  218. // Perform database sanity checks
  219. d, _ := blockDb.Get([]byte("ProtocolVersion"))
  220. protov := int(common.NewValue(d).Uint())
  221. if protov != config.ProtocolVersion && protov != 0 {
  222. path := filepath.Join(config.DataDir, "blockchain")
  223. return nil, fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, config.ProtocolVersion, path)
  224. }
  225. saveProtocolVersion(blockDb, config.ProtocolVersion)
  226. glog.V(logger.Info).Infof("Protocol Version: %v, Network Id: %v", config.ProtocolVersion, config.NetworkId)
  227. if !config.SkipBcVersionCheck {
  228. b, _ := blockDb.Get([]byte("BlockchainVersion"))
  229. bcVersion := int(common.NewValue(b).Uint())
  230. if bcVersion != config.BlockChainVersion && bcVersion != 0 {
  231. return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d). Run geth upgradedb.\n", bcVersion, config.BlockChainVersion)
  232. }
  233. saveBlockchainVersion(blockDb, config.BlockChainVersion)
  234. }
  235. glog.V(logger.Info).Infof("Blockchain DB Version: %d", config.BlockChainVersion)
  236. eth := &Ethereum{
  237. shutdownChan: make(chan bool),
  238. databasesClosed: make(chan bool),
  239. blockDb: blockDb,
  240. stateDb: stateDb,
  241. extraDb: extraDb,
  242. eventMux: &event.TypeMux{},
  243. accountManager: config.AccountManager,
  244. DataDir: config.DataDir,
  245. etherbase: common.HexToAddress(config.Etherbase),
  246. clientVersion: config.Name, // TODO should separate from Name
  247. ethVersionId: config.ProtocolVersion,
  248. netVersionId: config.NetworkId,
  249. NatSpec: config.NatSpec,
  250. MinerThreads: config.MinerThreads,
  251. SolcPath: config.SolcPath,
  252. AutoDAG: config.AutoDAG,
  253. }
  254. eth.pow = ethash.New()
  255. genesis := core.GenesisBlock(uint64(config.GenesisNonce), stateDb)
  256. eth.chainManager, err = core.NewChainManager(genesis, blockDb, stateDb, eth.pow, eth.EventMux())
  257. if err != nil {
  258. return nil, err
  259. }
  260. eth.downloader = downloader.New(eth.EventMux(), eth.chainManager.HasBlock, eth.chainManager.GetBlock)
  261. eth.txPool = core.NewTxPool(eth.EventMux(), eth.chainManager.State, eth.chainManager.GasLimit)
  262. eth.blockProcessor = core.NewBlockProcessor(stateDb, extraDb, eth.pow, eth.chainManager, eth.EventMux())
  263. eth.chainManager.SetProcessor(eth.blockProcessor)
  264. eth.miner = miner.New(eth, eth.EventMux(), eth.pow)
  265. eth.miner.SetGasPrice(config.GasPrice)
  266. eth.protocolManager = NewProtocolManager(config.ProtocolVersion, config.NetworkId, eth.eventMux, eth.txPool, eth.chainManager, eth.downloader)
  267. if config.Shh {
  268. eth.whisper = whisper.New()
  269. eth.shhVersionId = int(eth.whisper.Version())
  270. }
  271. netprv, err := config.nodeKey()
  272. if err != nil {
  273. return nil, err
  274. }
  275. protocols := []p2p.Protocol{eth.protocolManager.SubProtocol}
  276. if config.Shh {
  277. protocols = append(protocols, eth.whisper.Protocol())
  278. }
  279. eth.net = &p2p.Server{
  280. PrivateKey: netprv,
  281. Name: config.Name,
  282. MaxPeers: config.MaxPeers,
  283. MaxPendingPeers: config.MaxPendingPeers,
  284. Discovery: config.Discovery,
  285. Protocols: protocols,
  286. NAT: config.NAT,
  287. NoDial: !config.Dial,
  288. BootstrapNodes: config.parseBootNodes(),
  289. StaticNodes: config.parseNodes(staticNodes),
  290. TrustedNodes: config.parseNodes(trustedNodes),
  291. NodeDatabase: nodeDb,
  292. }
  293. if len(config.Port) > 0 {
  294. eth.net.ListenAddr = ":" + config.Port
  295. }
  296. vm.Debug = config.VmDebug
  297. return eth, nil
  298. }
  299. type NodeInfo struct {
  300. Name string
  301. NodeUrl string
  302. NodeID string
  303. IP string
  304. DiscPort int // UDP listening port for discovery protocol
  305. TCPPort int // TCP listening port for RLPx
  306. Td string
  307. ListenAddr string
  308. }
  309. func (s *Ethereum) NodeInfo() *NodeInfo {
  310. node := s.net.Self()
  311. return &NodeInfo{
  312. Name: s.Name(),
  313. NodeUrl: node.String(),
  314. NodeID: node.ID.String(),
  315. IP: node.IP.String(),
  316. DiscPort: int(node.UDP),
  317. TCPPort: int(node.TCP),
  318. ListenAddr: s.net.ListenAddr,
  319. Td: s.ChainManager().Td().String(),
  320. }
  321. }
  322. type PeerInfo struct {
  323. ID string
  324. Name string
  325. Caps string
  326. RemoteAddress string
  327. LocalAddress string
  328. }
  329. func newPeerInfo(peer *p2p.Peer) *PeerInfo {
  330. var caps []string
  331. for _, cap := range peer.Caps() {
  332. caps = append(caps, cap.String())
  333. }
  334. return &PeerInfo{
  335. ID: peer.ID().String(),
  336. Name: peer.Name(),
  337. Caps: strings.Join(caps, ", "),
  338. RemoteAddress: peer.RemoteAddr().String(),
  339. LocalAddress: peer.LocalAddr().String(),
  340. }
  341. }
  342. // PeersInfo returns an array of PeerInfo objects describing connected peers
  343. func (s *Ethereum) PeersInfo() (peersinfo []*PeerInfo) {
  344. for _, peer := range s.net.Peers() {
  345. if peer != nil {
  346. peersinfo = append(peersinfo, newPeerInfo(peer))
  347. }
  348. }
  349. return
  350. }
  351. func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
  352. s.chainManager.ResetWithGenesisBlock(gb)
  353. }
  354. func (s *Ethereum) StartMining(threads int) error {
  355. eb, err := s.Etherbase()
  356. if err != nil {
  357. err = fmt.Errorf("Cannot start mining without etherbase address: %v", err)
  358. glog.V(logger.Error).Infoln(err)
  359. return err
  360. }
  361. go s.miner.Start(eb, threads)
  362. return nil
  363. }
  364. func (s *Ethereum) Etherbase() (eb common.Address, err error) {
  365. eb = s.etherbase
  366. if (eb == common.Address{}) {
  367. primary, err := s.accountManager.Primary()
  368. if err != nil {
  369. return eb, err
  370. }
  371. if (primary == common.Address{}) {
  372. err = fmt.Errorf("no accounts found")
  373. return eb, err
  374. }
  375. eb = primary
  376. }
  377. return eb, nil
  378. }
  379. func (s *Ethereum) StopMining() { s.miner.Stop() }
  380. func (s *Ethereum) IsMining() bool { return s.miner.Mining() }
  381. func (s *Ethereum) Miner() *miner.Miner { return s.miner }
  382. // func (s *Ethereum) Logger() logger.LogSystem { return s.logger }
  383. func (s *Ethereum) Name() string { return s.net.Name }
  384. func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }
  385. func (s *Ethereum) ChainManager() *core.ChainManager { return s.chainManager }
  386. func (s *Ethereum) BlockProcessor() *core.BlockProcessor { return s.blockProcessor }
  387. func (s *Ethereum) TxPool() *core.TxPool { return s.txPool }
  388. func (s *Ethereum) Whisper() *whisper.Whisper { return s.whisper }
  389. func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
  390. func (s *Ethereum) BlockDb() common.Database { return s.blockDb }
  391. func (s *Ethereum) StateDb() common.Database { return s.stateDb }
  392. func (s *Ethereum) ExtraDb() common.Database { return s.extraDb }
  393. func (s *Ethereum) IsListening() bool { return true } // Always listening
  394. func (s *Ethereum) PeerCount() int { return s.net.PeerCount() }
  395. func (s *Ethereum) Peers() []*p2p.Peer { return s.net.Peers() }
  396. func (s *Ethereum) MaxPeers() int { return s.net.MaxPeers }
  397. func (s *Ethereum) ClientVersion() string { return s.clientVersion }
  398. func (s *Ethereum) EthVersion() int { return s.ethVersionId }
  399. func (s *Ethereum) NetVersion() int { return s.netVersionId }
  400. func (s *Ethereum) ShhVersion() int { return s.shhVersionId }
  401. func (s *Ethereum) Downloader() *downloader.Downloader { return s.downloader }
  402. // Start the ethereum
  403. func (s *Ethereum) Start() error {
  404. jsonlogger.LogJson(&logger.LogStarting{
  405. ClientString: s.net.Name,
  406. ProtocolVersion: ProtocolVersion,
  407. })
  408. err := s.net.Start()
  409. if err != nil {
  410. return err
  411. }
  412. // periodically flush databases
  413. go s.syncDatabases()
  414. if s.AutoDAG {
  415. s.StartAutoDAG()
  416. }
  417. s.protocolManager.Start()
  418. if s.whisper != nil {
  419. s.whisper.Start()
  420. }
  421. glog.V(logger.Info).Infoln("Server started")
  422. return nil
  423. }
  424. // sync databases every minute. If flushing fails we exit immediatly. The system
  425. // may not continue under any circumstances.
  426. func (s *Ethereum) syncDatabases() {
  427. ticker := time.NewTicker(1 * time.Minute)
  428. done:
  429. for {
  430. select {
  431. case <-ticker.C:
  432. // don't change the order of database flushes
  433. if err := s.extraDb.Flush(); err != nil {
  434. glog.Fatalf("fatal error: flush extraDb: %v (Restart your node. We are aware of this issue)\n", err)
  435. }
  436. if err := s.stateDb.Flush(); err != nil {
  437. glog.Fatalf("fatal error: flush stateDb: %v (Restart your node. We are aware of this issue)\n", err)
  438. }
  439. if err := s.blockDb.Flush(); err != nil {
  440. glog.Fatalf("fatal error: flush blockDb: %v (Restart your node. We are aware of this issue)\n", err)
  441. }
  442. case <-s.shutdownChan:
  443. break done
  444. }
  445. }
  446. s.blockDb.Close()
  447. s.stateDb.Close()
  448. s.extraDb.Close()
  449. close(s.databasesClosed)
  450. }
  451. func (s *Ethereum) StartForTest() {
  452. jsonlogger.LogJson(&logger.LogStarting{
  453. ClientString: s.net.Name,
  454. ProtocolVersion: ProtocolVersion,
  455. })
  456. }
  457. // AddPeer connects to the given node and maintains the connection until the
  458. // server is shut down. If the connection fails for any reason, the server will
  459. // attempt to reconnect the peer.
  460. func (self *Ethereum) AddPeer(nodeURL string) error {
  461. n, err := discover.ParseNode(nodeURL)
  462. if err != nil {
  463. return fmt.Errorf("invalid node URL: %v", err)
  464. }
  465. self.net.AddPeer(n)
  466. return nil
  467. }
  468. func (s *Ethereum) Stop() {
  469. s.net.Stop()
  470. s.chainManager.Stop()
  471. s.protocolManager.Stop()
  472. s.txPool.Stop()
  473. s.eventMux.Stop()
  474. if s.whisper != nil {
  475. s.whisper.Stop()
  476. }
  477. s.StopAutoDAG()
  478. close(s.shutdownChan)
  479. }
  480. // This function will wait for a shutdown and resumes main thread execution
  481. func (s *Ethereum) WaitForShutdown() {
  482. <-s.databasesClosed
  483. <-s.shutdownChan
  484. }
  485. // StartAutoDAG() spawns a go routine that checks the DAG every autoDAGcheckInterval
  486. // by default that is 10 times per epoch
  487. // in epoch n, if we past autoDAGepochHeight within-epoch blocks,
  488. // it calls ethash.MakeDAG to pregenerate the DAG for the next epoch n+1
  489. // if it does not exist yet as well as remove the DAG for epoch n-1
  490. // the loop quits if autodagquit channel is closed, it can safely restart and
  491. // stop any number of times.
  492. // For any more sophisticated pattern of DAG generation, use CLI subcommand
  493. // makedag
  494. func (self *Ethereum) StartAutoDAG() {
  495. if self.autodagquit != nil {
  496. return // already started
  497. }
  498. go func() {
  499. glog.V(logger.Info).Infof("Automatic pregeneration of ethash DAG ON (ethash dir: %s)", ethash.DefaultDir)
  500. var nextEpoch uint64
  501. timer := time.After(0)
  502. self.autodagquit = make(chan bool)
  503. for {
  504. select {
  505. case <-timer:
  506. glog.V(logger.Info).Infof("checking DAG (ethash dir: %s)", ethash.DefaultDir)
  507. currentBlock := self.ChainManager().CurrentBlock().NumberU64()
  508. thisEpoch := currentBlock / epochLength
  509. if nextEpoch <= thisEpoch {
  510. if currentBlock%epochLength > autoDAGepochHeight {
  511. if thisEpoch > 0 {
  512. previousDag, previousDagFull := dagFiles(thisEpoch - 1)
  513. os.Remove(filepath.Join(ethash.DefaultDir, previousDag))
  514. os.Remove(filepath.Join(ethash.DefaultDir, previousDagFull))
  515. glog.V(logger.Info).Infof("removed DAG for epoch %d (%s)", thisEpoch-1, previousDag)
  516. }
  517. nextEpoch = thisEpoch + 1
  518. dag, _ := dagFiles(nextEpoch)
  519. if _, err := os.Stat(dag); os.IsNotExist(err) {
  520. glog.V(logger.Info).Infof("Pregenerating DAG for epoch %d (%s)", nextEpoch, dag)
  521. err := ethash.MakeDAG(nextEpoch*epochLength, "") // "" -> ethash.DefaultDir
  522. if err != nil {
  523. glog.V(logger.Error).Infof("Error generating DAG for epoch %d (%s)", nextEpoch, dag)
  524. return
  525. }
  526. } else {
  527. glog.V(logger.Error).Infof("DAG for epoch %d (%s)", nextEpoch, dag)
  528. }
  529. }
  530. }
  531. timer = time.After(autoDAGcheckInterval)
  532. case <-self.autodagquit:
  533. return
  534. }
  535. }
  536. }()
  537. }
  538. // dagFiles(epoch) returns the two alternative DAG filenames (not a path)
  539. // 1) <revision>-<hex(seedhash[8])> 2) full-R<revision>-<hex(seedhash[8])>
  540. func dagFiles(epoch uint64) (string, string) {
  541. seedHash, _ := ethash.GetSeedHash(epoch * epochLength)
  542. dag := fmt.Sprintf("full-R%d-%x", ethashRevision, seedHash[:8])
  543. return dag, "full-R" + dag
  544. }
  545. // stopAutoDAG stops automatic DAG pregeneration by quitting the loop
  546. func (self *Ethereum) StopAutoDAG() {
  547. if self.autodagquit != nil {
  548. close(self.autodagquit)
  549. self.autodagquit = nil
  550. }
  551. glog.V(logger.Info).Infof("Automatic pregeneration of ethash DAG OFF (ethash dir: %s)", ethash.DefaultDir)
  552. }
  553. func saveProtocolVersion(db common.Database, protov int) {
  554. d, _ := db.Get([]byte("ProtocolVersion"))
  555. protocolVersion := common.NewValue(d).Uint()
  556. if protocolVersion == 0 {
  557. db.Put([]byte("ProtocolVersion"), common.NewValue(protov).Bytes())
  558. }
  559. }
  560. func saveBlockchainVersion(db common.Database, bcVersion int) {
  561. d, _ := db.Get([]byte("BlockchainVersion"))
  562. blockchainVersion := common.NewValue(d).Uint()
  563. if blockchainVersion == 0 {
  564. db.Put([]byte("BlockchainVersion"), common.NewValue(bcVersion).Bytes())
  565. }
  566. }
  567. func (self *Ethereum) Solc() (*compiler.Solidity, error) {
  568. var err error
  569. if self.solc == nil {
  570. self.solc, err = compiler.New(self.SolcPath)
  571. }
  572. return self.solc, err
  573. }
  574. // set in js console via admin interface or wrapper from cli flags
  575. func (self *Ethereum) SetSolc(solcPath string) (*compiler.Solidity, error) {
  576. self.SolcPath = solcPath
  577. self.solc = nil
  578. return self.Solc()
  579. }