backend.go 17 KB

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