backend.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  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. "errors"
  20. "fmt"
  21. "math/big"
  22. "os"
  23. "path/filepath"
  24. "regexp"
  25. "strings"
  26. "sync"
  27. "time"
  28. "github.com/ethereum/ethash"
  29. "github.com/ethereum/go-ethereum/accounts"
  30. "github.com/ethereum/go-ethereum/common"
  31. "github.com/ethereum/go-ethereum/core"
  32. "github.com/ethereum/go-ethereum/core/types"
  33. "github.com/ethereum/go-ethereum/eth/downloader"
  34. "github.com/ethereum/go-ethereum/eth/filters"
  35. "github.com/ethereum/go-ethereum/eth/gasprice"
  36. "github.com/ethereum/go-ethereum/ethdb"
  37. "github.com/ethereum/go-ethereum/event"
  38. "github.com/ethereum/go-ethereum/internal/ethapi"
  39. "github.com/ethereum/go-ethereum/logger"
  40. "github.com/ethereum/go-ethereum/logger/glog"
  41. "github.com/ethereum/go-ethereum/miner"
  42. "github.com/ethereum/go-ethereum/node"
  43. "github.com/ethereum/go-ethereum/p2p"
  44. "github.com/ethereum/go-ethereum/params"
  45. "github.com/ethereum/go-ethereum/rpc"
  46. )
  47. const (
  48. epochLength = 30000
  49. ethashRevision = 23
  50. autoDAGcheckInterval = 10 * time.Hour
  51. autoDAGepochHeight = epochLength / 2
  52. )
  53. var (
  54. datadirInUseErrnos = map[uint]bool{11: true, 32: true, 35: true}
  55. portInUseErrRE = regexp.MustCompile("address already in use")
  56. )
  57. type Config struct {
  58. ChainConfig *params.ChainConfig // chain configuration
  59. NetworkId int // Network ID to use for selecting peers to connect to
  60. Genesis string // Genesis JSON to seed the chain database with
  61. FastSync bool // Enables the state download based fast synchronisation algorithm
  62. LightMode bool // Running in light client mode
  63. LightServ int // Maximum percentage of time allowed for serving LES requests
  64. LightPeers int // Maximum number of LES client peers
  65. MaxPeers int // Maximum number of global peers
  66. SkipBcVersionCheck bool // e.g. blockchain export
  67. DatabaseCache int
  68. DatabaseHandles int
  69. NatSpec bool
  70. DocRoot string
  71. AutoDAG bool
  72. PowTest bool
  73. PowShared bool
  74. ExtraData []byte
  75. Etherbase common.Address
  76. GasPrice *big.Int
  77. MinerThreads int
  78. SolcPath string
  79. GpoMinGasPrice *big.Int
  80. GpoMaxGasPrice *big.Int
  81. GpoFullBlockRatio int
  82. GpobaseStepDown int
  83. GpobaseStepUp int
  84. GpobaseCorrectionFactor int
  85. EnableJit bool
  86. ForceJit bool
  87. TestGenesisBlock *types.Block // Genesis block to seed the chain database with (testing only!)
  88. TestGenesisState ethdb.Database // Genesis state to seed the database with (testing only!)
  89. }
  90. type LesServer interface {
  91. Start(srvr *p2p.Server)
  92. Synced()
  93. Stop()
  94. Protocols() []p2p.Protocol
  95. }
  96. // Ethereum implements the Ethereum full node service.
  97. type Ethereum struct {
  98. chainConfig *params.ChainConfig
  99. // Channel for shutting down the service
  100. shutdownChan chan bool // Channel for shutting down the ethereum
  101. stopDbUpgrade func() // stop chain db sequential key upgrade
  102. // Handlers
  103. txPool *core.TxPool
  104. txMu sync.Mutex
  105. blockchain *core.BlockChain
  106. protocolManager *ProtocolManager
  107. lesServer LesServer
  108. // DB interfaces
  109. chainDb ethdb.Database // Block chain database
  110. eventMux *event.TypeMux
  111. pow *ethash.Ethash
  112. accountManager *accounts.Manager
  113. ApiBackend *EthApiBackend
  114. miner *miner.Miner
  115. Mining bool
  116. MinerThreads int
  117. AutoDAG bool
  118. autodagquit chan bool
  119. etherbase common.Address
  120. solcPath string
  121. NatSpec bool
  122. PowTest bool
  123. netVersionId int
  124. netRPCService *ethapi.PublicNetAPI
  125. }
  126. func (s *Ethereum) AddLesServer(ls LesServer) {
  127. s.lesServer = ls
  128. s.protocolManager.lesServer = ls
  129. }
  130. // New creates a new Ethereum object (including the
  131. // initialisation of the common Ethereum object)
  132. func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
  133. chainDb, err := CreateDB(ctx, config, "chaindata")
  134. if err != nil {
  135. return nil, err
  136. }
  137. stopDbUpgrade := upgradeSequentialKeys(chainDb)
  138. if err := SetupGenesisBlock(&chainDb, config); err != nil {
  139. return nil, err
  140. }
  141. pow, err := CreatePoW(config)
  142. if err != nil {
  143. return nil, err
  144. }
  145. eth := &Ethereum{
  146. chainDb: chainDb,
  147. eventMux: ctx.EventMux,
  148. accountManager: ctx.AccountManager,
  149. pow: pow,
  150. shutdownChan: make(chan bool),
  151. stopDbUpgrade: stopDbUpgrade,
  152. netVersionId: config.NetworkId,
  153. NatSpec: config.NatSpec,
  154. PowTest: config.PowTest,
  155. etherbase: config.Etherbase,
  156. MinerThreads: config.MinerThreads,
  157. AutoDAG: config.AutoDAG,
  158. solcPath: config.SolcPath,
  159. }
  160. if err := upgradeChainDatabase(chainDb); err != nil {
  161. return nil, err
  162. }
  163. if err := addMipmapBloomBins(chainDb); err != nil {
  164. return nil, err
  165. }
  166. glog.V(logger.Info).Infof("Protocol Versions: %v, Network Id: %v", ProtocolVersions, config.NetworkId)
  167. if !config.SkipBcVersionCheck {
  168. bcVersion := core.GetBlockChainVersion(chainDb)
  169. if bcVersion != core.BlockChainVersion && bcVersion != 0 {
  170. return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d). Run geth upgradedb.\n", bcVersion, core.BlockChainVersion)
  171. }
  172. core.WriteBlockChainVersion(chainDb, core.BlockChainVersion)
  173. }
  174. // load the genesis block or write a new one if no genesis
  175. // block is prenent in the database.
  176. genesis := core.GetBlock(chainDb, core.GetCanonicalHash(chainDb, 0), 0)
  177. if genesis == nil {
  178. genesis, err = core.WriteDefaultGenesisBlock(chainDb)
  179. if err != nil {
  180. return nil, err
  181. }
  182. glog.V(logger.Info).Infoln("WARNING: Wrote default ethereum genesis block")
  183. }
  184. if config.ChainConfig == nil {
  185. return nil, errors.New("missing chain config")
  186. }
  187. core.WriteChainConfig(chainDb, genesis.Hash(), config.ChainConfig)
  188. eth.chainConfig = config.ChainConfig
  189. glog.V(logger.Info).Infoln("Chain config:", eth.chainConfig)
  190. eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.pow, eth.EventMux())
  191. if err != nil {
  192. if err == core.ErrNoGenesis {
  193. return nil, fmt.Errorf(`No chain found. Please initialise a new chain using the "init" subcommand.`)
  194. }
  195. return nil, err
  196. }
  197. newPool := core.NewTxPool(eth.chainConfig, eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
  198. eth.txPool = newPool
  199. maxPeers := config.MaxPeers
  200. if config.LightServ > 0 {
  201. // if we are running a light server, limit the number of ETH peers so that we reserve some space for incoming LES connections
  202. // temporary solution until the new peer connectivity API is finished
  203. halfPeers := maxPeers / 2
  204. maxPeers -= config.LightPeers
  205. if maxPeers < halfPeers {
  206. maxPeers = halfPeers
  207. }
  208. }
  209. if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.FastSync, config.NetworkId, maxPeers, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb); err != nil {
  210. return nil, err
  211. }
  212. eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.pow)
  213. eth.miner.SetGasPrice(config.GasPrice)
  214. eth.miner.SetExtra(config.ExtraData)
  215. gpoParams := &gasprice.GpoParams{
  216. GpoMinGasPrice: config.GpoMinGasPrice,
  217. GpoMaxGasPrice: config.GpoMaxGasPrice,
  218. GpoFullBlockRatio: config.GpoFullBlockRatio,
  219. GpobaseStepDown: config.GpobaseStepDown,
  220. GpobaseStepUp: config.GpobaseStepUp,
  221. GpobaseCorrectionFactor: config.GpobaseCorrectionFactor,
  222. }
  223. gpo := gasprice.NewGasPriceOracle(eth.blockchain, chainDb, eth.eventMux, gpoParams)
  224. eth.ApiBackend = &EthApiBackend{eth, gpo}
  225. return eth, nil
  226. }
  227. // CreateDB creates the chain database.
  228. func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Database, error) {
  229. db, err := ctx.OpenDatabase(name, config.DatabaseCache, config.DatabaseHandles)
  230. if db, ok := db.(*ethdb.LDBDatabase); ok {
  231. db.Meter("eth/db/chaindata/")
  232. }
  233. return db, err
  234. }
  235. // SetupGenesisBlock initializes the genesis block for an Ethereum service
  236. func SetupGenesisBlock(chainDb *ethdb.Database, config *Config) error {
  237. // Load up any custom genesis block if requested
  238. if len(config.Genesis) > 0 {
  239. block, err := core.WriteGenesisBlock(*chainDb, strings.NewReader(config.Genesis))
  240. if err != nil {
  241. return err
  242. }
  243. glog.V(logger.Info).Infof("Successfully wrote custom genesis block: %x", block.Hash())
  244. }
  245. // Load up a test setup if directly injected
  246. if config.TestGenesisState != nil {
  247. *chainDb = config.TestGenesisState
  248. }
  249. if config.TestGenesisBlock != nil {
  250. core.WriteTd(*chainDb, config.TestGenesisBlock.Hash(), config.TestGenesisBlock.NumberU64(), config.TestGenesisBlock.Difficulty())
  251. core.WriteBlock(*chainDb, config.TestGenesisBlock)
  252. core.WriteCanonicalHash(*chainDb, config.TestGenesisBlock.Hash(), config.TestGenesisBlock.NumberU64())
  253. core.WriteHeadBlockHash(*chainDb, config.TestGenesisBlock.Hash())
  254. }
  255. return nil
  256. }
  257. // CreatePoW creates the required type of PoW instance for an Ethereum service
  258. func CreatePoW(config *Config) (*ethash.Ethash, error) {
  259. switch {
  260. case config.PowTest:
  261. glog.V(logger.Info).Infof("ethash used in test mode")
  262. return ethash.NewForTesting()
  263. case config.PowShared:
  264. glog.V(logger.Info).Infof("ethash used in shared mode")
  265. return ethash.NewShared(), nil
  266. default:
  267. return ethash.New(), nil
  268. }
  269. }
  270. // APIs returns the collection of RPC services the ethereum package offers.
  271. // NOTE, some of these services probably need to be moved to somewhere else.
  272. func (s *Ethereum) APIs() []rpc.API {
  273. return append(ethapi.GetAPIs(s.ApiBackend, s.solcPath), []rpc.API{
  274. {
  275. Namespace: "eth",
  276. Version: "1.0",
  277. Service: NewPublicEthereumAPI(s),
  278. Public: true,
  279. }, {
  280. Namespace: "eth",
  281. Version: "1.0",
  282. Service: NewPublicMinerAPI(s),
  283. Public: true,
  284. }, {
  285. Namespace: "eth",
  286. Version: "1.0",
  287. Service: downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux),
  288. Public: true,
  289. }, {
  290. Namespace: "miner",
  291. Version: "1.0",
  292. Service: NewPrivateMinerAPI(s),
  293. Public: false,
  294. }, {
  295. Namespace: "eth",
  296. Version: "1.0",
  297. Service: filters.NewPublicFilterAPI(s.ApiBackend, false),
  298. Public: true,
  299. }, {
  300. Namespace: "admin",
  301. Version: "1.0",
  302. Service: NewPrivateAdminAPI(s),
  303. }, {
  304. Namespace: "debug",
  305. Version: "1.0",
  306. Service: NewPublicDebugAPI(s),
  307. Public: true,
  308. }, {
  309. Namespace: "debug",
  310. Version: "1.0",
  311. Service: NewPrivateDebugAPI(s.chainConfig, s),
  312. }, {
  313. Namespace: "net",
  314. Version: "1.0",
  315. Service: s.netRPCService,
  316. Public: true,
  317. },
  318. }...)
  319. }
  320. func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
  321. s.blockchain.ResetWithGenesisBlock(gb)
  322. }
  323. func (s *Ethereum) Etherbase() (eb common.Address, err error) {
  324. eb = s.etherbase
  325. if (eb == common.Address{}) {
  326. firstAccount, err := s.AccountManager().AccountByIndex(0)
  327. eb = firstAccount.Address
  328. if err != nil {
  329. return eb, fmt.Errorf("etherbase address must be explicitly specified")
  330. }
  331. }
  332. return eb, nil
  333. }
  334. // set in js console via admin interface or wrapper from cli flags
  335. func (self *Ethereum) SetEtherbase(etherbase common.Address) {
  336. self.etherbase = etherbase
  337. self.miner.SetEtherbase(etherbase)
  338. }
  339. func (s *Ethereum) StartMining(threads int) error {
  340. eb, err := s.Etherbase()
  341. if err != nil {
  342. err = fmt.Errorf("Cannot start mining without etherbase address: %v", err)
  343. glog.V(logger.Error).Infoln(err)
  344. return err
  345. }
  346. go s.miner.Start(eb, threads)
  347. return nil
  348. }
  349. func (s *Ethereum) StopMining() { s.miner.Stop() }
  350. func (s *Ethereum) IsMining() bool { return s.miner.Mining() }
  351. func (s *Ethereum) Miner() *miner.Miner { return s.miner }
  352. func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }
  353. func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
  354. func (s *Ethereum) TxPool() *core.TxPool { return s.txPool }
  355. func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
  356. func (s *Ethereum) Pow() *ethash.Ethash { return s.pow }
  357. func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb }
  358. func (s *Ethereum) IsListening() bool { return true } // Always listening
  359. func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) }
  360. func (s *Ethereum) NetVersion() int { return s.netVersionId }
  361. func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader }
  362. // Protocols implements node.Service, returning all the currently configured
  363. // network protocols to start.
  364. func (s *Ethereum) Protocols() []p2p.Protocol {
  365. if s.lesServer == nil {
  366. return s.protocolManager.SubProtocols
  367. } else {
  368. return append(s.protocolManager.SubProtocols, s.lesServer.Protocols()...)
  369. }
  370. }
  371. // Start implements node.Service, starting all internal goroutines needed by the
  372. // Ethereum protocol implementation.
  373. func (s *Ethereum) Start(srvr *p2p.Server) error {
  374. s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.NetVersion())
  375. if s.AutoDAG {
  376. s.StartAutoDAG()
  377. }
  378. s.protocolManager.Start()
  379. if s.lesServer != nil {
  380. s.lesServer.Start(srvr)
  381. }
  382. return nil
  383. }
  384. // Stop implements node.Service, terminating all internal goroutines used by the
  385. // Ethereum protocol.
  386. func (s *Ethereum) Stop() error {
  387. if s.stopDbUpgrade != nil {
  388. s.stopDbUpgrade()
  389. }
  390. s.blockchain.Stop()
  391. s.protocolManager.Stop()
  392. if s.lesServer != nil {
  393. s.lesServer.Stop()
  394. }
  395. s.txPool.Stop()
  396. s.miner.Stop()
  397. s.eventMux.Stop()
  398. s.StopAutoDAG()
  399. s.chainDb.Close()
  400. close(s.shutdownChan)
  401. return nil
  402. }
  403. // This function will wait for a shutdown and resumes main thread execution
  404. func (s *Ethereum) WaitForShutdown() {
  405. <-s.shutdownChan
  406. }
  407. // StartAutoDAG() spawns a go routine that checks the DAG every autoDAGcheckInterval
  408. // by default that is 10 times per epoch
  409. // in epoch n, if we past autoDAGepochHeight within-epoch blocks,
  410. // it calls ethash.MakeDAG to pregenerate the DAG for the next epoch n+1
  411. // if it does not exist yet as well as remove the DAG for epoch n-1
  412. // the loop quits if autodagquit channel is closed, it can safely restart and
  413. // stop any number of times.
  414. // For any more sophisticated pattern of DAG generation, use CLI subcommand
  415. // makedag
  416. func (self *Ethereum) StartAutoDAG() {
  417. if self.autodagquit != nil {
  418. return // already started
  419. }
  420. go func() {
  421. glog.V(logger.Info).Infof("Automatic pregeneration of ethash DAG ON (ethash dir: %s)", ethash.DefaultDir)
  422. var nextEpoch uint64
  423. timer := time.After(0)
  424. self.autodagquit = make(chan bool)
  425. for {
  426. select {
  427. case <-timer:
  428. glog.V(logger.Info).Infof("checking DAG (ethash dir: %s)", ethash.DefaultDir)
  429. currentBlock := self.BlockChain().CurrentBlock().NumberU64()
  430. thisEpoch := currentBlock / epochLength
  431. if nextEpoch <= thisEpoch {
  432. if currentBlock%epochLength > autoDAGepochHeight {
  433. if thisEpoch > 0 {
  434. previousDag, previousDagFull := dagFiles(thisEpoch - 1)
  435. os.Remove(filepath.Join(ethash.DefaultDir, previousDag))
  436. os.Remove(filepath.Join(ethash.DefaultDir, previousDagFull))
  437. glog.V(logger.Info).Infof("removed DAG for epoch %d (%s)", thisEpoch-1, previousDag)
  438. }
  439. nextEpoch = thisEpoch + 1
  440. dag, _ := dagFiles(nextEpoch)
  441. if _, err := os.Stat(dag); os.IsNotExist(err) {
  442. glog.V(logger.Info).Infof("Pregenerating DAG for epoch %d (%s)", nextEpoch, dag)
  443. err := ethash.MakeDAG(nextEpoch*epochLength, "") // "" -> ethash.DefaultDir
  444. if err != nil {
  445. glog.V(logger.Error).Infof("Error generating DAG for epoch %d (%s)", nextEpoch, dag)
  446. return
  447. }
  448. } else {
  449. glog.V(logger.Error).Infof("DAG for epoch %d (%s)", nextEpoch, dag)
  450. }
  451. }
  452. }
  453. timer = time.After(autoDAGcheckInterval)
  454. case <-self.autodagquit:
  455. return
  456. }
  457. }
  458. }()
  459. }
  460. // stopAutoDAG stops automatic DAG pregeneration by quitting the loop
  461. func (self *Ethereum) StopAutoDAG() {
  462. if self.autodagquit != nil {
  463. close(self.autodagquit)
  464. self.autodagquit = nil
  465. }
  466. glog.V(logger.Info).Infof("Automatic pregeneration of ethash DAG OFF (ethash dir: %s)", ethash.DefaultDir)
  467. }
  468. // dagFiles(epoch) returns the two alternative DAG filenames (not a path)
  469. // 1) <revision>-<hex(seedhash[8])> 2) full-R<revision>-<hex(seedhash[8])>
  470. func dagFiles(epoch uint64) (string, string) {
  471. seedHash, _ := ethash.GetSeedHash(epoch * epochLength)
  472. dag := fmt.Sprintf("full-R%d-%x", ethashRevision, seedHash[:8])
  473. return dag, "full-R" + dag
  474. }