backend.go 17 KB

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