backend.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  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. glog.V(logger.Info).Infoln("Chain config:", eth.chainConfig)
  192. eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.pow, eth.EventMux())
  193. if err != nil {
  194. if err == core.ErrNoGenesis {
  195. return nil, fmt.Errorf(`No chain found. Please initialise a new chain using the "init" subcommand.`)
  196. }
  197. return nil, err
  198. }
  199. newPool := core.NewTxPool(eth.chainConfig, eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
  200. eth.txPool = newPool
  201. maxPeers := config.MaxPeers
  202. if config.LightServ > 0 {
  203. // if we are running a light server, limit the number of ETH peers so that we reserve some space for incoming LES connections
  204. // temporary solution until the new peer connectivity API is finished
  205. halfPeers := maxPeers / 2
  206. maxPeers -= config.LightPeers
  207. if maxPeers < halfPeers {
  208. maxPeers = halfPeers
  209. }
  210. }
  211. if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.FastSync, config.NetworkId, maxPeers, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb); err != nil {
  212. return nil, err
  213. }
  214. eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.pow)
  215. eth.miner.SetGasPrice(config.GasPrice)
  216. eth.miner.SetExtra(config.ExtraData)
  217. gpoParams := &gasprice.GpoParams{
  218. GpoMinGasPrice: config.GpoMinGasPrice,
  219. GpoMaxGasPrice: config.GpoMaxGasPrice,
  220. GpoFullBlockRatio: config.GpoFullBlockRatio,
  221. GpobaseStepDown: config.GpobaseStepDown,
  222. GpobaseStepUp: config.GpobaseStepUp,
  223. GpobaseCorrectionFactor: config.GpobaseCorrectionFactor,
  224. }
  225. gpo := gasprice.NewGasPriceOracle(eth.blockchain, chainDb, eth.eventMux, gpoParams)
  226. eth.ApiBackend = &EthApiBackend{eth, gpo}
  227. return eth, nil
  228. }
  229. // CreateDB creates the chain database.
  230. func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Database, error) {
  231. db, err := ctx.OpenDatabase(name, config.DatabaseCache, config.DatabaseHandles)
  232. if db, ok := db.(*ethdb.LDBDatabase); ok {
  233. db.Meter("eth/db/chaindata/")
  234. }
  235. return db, err
  236. }
  237. // SetupGenesisBlock initializes the genesis block for an Ethereum service
  238. func SetupGenesisBlock(chainDb *ethdb.Database, config *Config) error {
  239. // Load up any custom genesis block if requested
  240. if len(config.Genesis) > 0 {
  241. block, err := core.WriteGenesisBlock(*chainDb, strings.NewReader(config.Genesis))
  242. if err != nil {
  243. return err
  244. }
  245. glog.V(logger.Info).Infof("Successfully wrote custom genesis block: %x", block.Hash())
  246. }
  247. // Load up a test setup if directly injected
  248. if config.TestGenesisState != nil {
  249. *chainDb = config.TestGenesisState
  250. }
  251. if config.TestGenesisBlock != nil {
  252. core.WriteTd(*chainDb, config.TestGenesisBlock.Hash(), config.TestGenesisBlock.NumberU64(), config.TestGenesisBlock.Difficulty())
  253. core.WriteBlock(*chainDb, config.TestGenesisBlock)
  254. core.WriteCanonicalHash(*chainDb, config.TestGenesisBlock.Hash(), config.TestGenesisBlock.NumberU64())
  255. core.WriteHeadBlockHash(*chainDb, config.TestGenesisBlock.Hash())
  256. }
  257. return nil
  258. }
  259. // CreatePoW creates the required type of PoW instance for an Ethereum service
  260. func CreatePoW(config *Config) (*ethash.Ethash, error) {
  261. switch {
  262. case config.PowTest:
  263. glog.V(logger.Info).Infof("ethash used in test mode")
  264. return ethash.NewForTesting()
  265. case config.PowShared:
  266. glog.V(logger.Info).Infof("ethash used in shared mode")
  267. return ethash.NewShared(), nil
  268. default:
  269. return ethash.New(), nil
  270. }
  271. }
  272. // APIs returns the collection of RPC services the ethereum package offers.
  273. // NOTE, some of these services probably need to be moved to somewhere else.
  274. func (s *Ethereum) APIs() []rpc.API {
  275. return append(ethapi.GetAPIs(s.ApiBackend, s.solcPath), []rpc.API{
  276. {
  277. Namespace: "eth",
  278. Version: "1.0",
  279. Service: NewPublicEthereumAPI(s),
  280. Public: true,
  281. }, {
  282. Namespace: "eth",
  283. Version: "1.0",
  284. Service: NewPublicMinerAPI(s),
  285. Public: true,
  286. }, {
  287. Namespace: "eth",
  288. Version: "1.0",
  289. Service: downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux),
  290. Public: true,
  291. }, {
  292. Namespace: "miner",
  293. Version: "1.0",
  294. Service: NewPrivateMinerAPI(s),
  295. Public: false,
  296. }, {
  297. Namespace: "eth",
  298. Version: "1.0",
  299. Service: filters.NewPublicFilterAPI(s.ApiBackend, false),
  300. Public: true,
  301. }, {
  302. Namespace: "admin",
  303. Version: "1.0",
  304. Service: NewPrivateAdminAPI(s),
  305. }, {
  306. Namespace: "debug",
  307. Version: "1.0",
  308. Service: NewPublicDebugAPI(s),
  309. Public: true,
  310. }, {
  311. Namespace: "debug",
  312. Version: "1.0",
  313. Service: NewPrivateDebugAPI(s.chainConfig, s),
  314. }, {
  315. Namespace: "net",
  316. Version: "1.0",
  317. Service: s.netRPCService,
  318. Public: true,
  319. }, {
  320. Namespace: "admin",
  321. Version: "1.0",
  322. Service: ethreg.NewPrivateRegistarAPI(s.chainConfig, s.blockchain, s.chainDb, s.txPool, s.accountManager),
  323. },
  324. }...)
  325. }
  326. func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
  327. s.blockchain.ResetWithGenesisBlock(gb)
  328. }
  329. func (s *Ethereum) Etherbase() (eb common.Address, err error) {
  330. eb = s.etherbase
  331. if (eb == common.Address{}) {
  332. firstAccount, err := s.AccountManager().AccountByIndex(0)
  333. eb = firstAccount.Address
  334. if err != nil {
  335. return eb, fmt.Errorf("etherbase address must be explicitly specified")
  336. }
  337. }
  338. return eb, nil
  339. }
  340. // set in js console via admin interface or wrapper from cli flags
  341. func (self *Ethereum) SetEtherbase(etherbase common.Address) {
  342. self.etherbase = etherbase
  343. self.miner.SetEtherbase(etherbase)
  344. }
  345. func (s *Ethereum) StartMining(threads int) error {
  346. eb, err := s.Etherbase()
  347. if err != nil {
  348. err = fmt.Errorf("Cannot start mining without etherbase address: %v", err)
  349. glog.V(logger.Error).Infoln(err)
  350. return err
  351. }
  352. go s.miner.Start(eb, threads)
  353. return nil
  354. }
  355. func (s *Ethereum) StopMining() { s.miner.Stop() }
  356. func (s *Ethereum) IsMining() bool { return s.miner.Mining() }
  357. func (s *Ethereum) Miner() *miner.Miner { return s.miner }
  358. func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }
  359. func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
  360. func (s *Ethereum) TxPool() *core.TxPool { return s.txPool }
  361. func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
  362. func (s *Ethereum) Pow() *ethash.Ethash { return s.pow }
  363. func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb }
  364. func (s *Ethereum) IsListening() bool { return true } // Always listening
  365. func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) }
  366. func (s *Ethereum) NetVersion() int { return s.netVersionId }
  367. func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader }
  368. // Protocols implements node.Service, returning all the currently configured
  369. // network protocols to start.
  370. func (s *Ethereum) Protocols() []p2p.Protocol {
  371. if s.lesServer == nil {
  372. return s.protocolManager.SubProtocols
  373. } else {
  374. return append(s.protocolManager.SubProtocols, s.lesServer.Protocols()...)
  375. }
  376. }
  377. // Start implements node.Service, starting all internal goroutines needed by the
  378. // Ethereum protocol implementation.
  379. func (s *Ethereum) Start(srvr *p2p.Server) error {
  380. s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.NetVersion())
  381. if s.AutoDAG {
  382. s.StartAutoDAG()
  383. }
  384. s.protocolManager.Start()
  385. if s.lesServer != nil {
  386. s.lesServer.Start(srvr)
  387. }
  388. return nil
  389. }
  390. // Stop implements node.Service, terminating all internal goroutines used by the
  391. // Ethereum protocol.
  392. func (s *Ethereum) Stop() error {
  393. if s.stopDbUpgrade != nil {
  394. s.stopDbUpgrade()
  395. }
  396. s.blockchain.Stop()
  397. s.protocolManager.Stop()
  398. if s.lesServer != nil {
  399. s.lesServer.Stop()
  400. }
  401. s.txPool.Stop()
  402. s.miner.Stop()
  403. s.eventMux.Stop()
  404. s.StopAutoDAG()
  405. s.chainDb.Close()
  406. close(s.shutdownChan)
  407. return nil
  408. }
  409. // This function will wait for a shutdown and resumes main thread execution
  410. func (s *Ethereum) WaitForShutdown() {
  411. <-s.shutdownChan
  412. }
  413. // StartAutoDAG() spawns a go routine that checks the DAG every autoDAGcheckInterval
  414. // by default that is 10 times per epoch
  415. // in epoch n, if we past autoDAGepochHeight within-epoch blocks,
  416. // it calls ethash.MakeDAG to pregenerate the DAG for the next epoch n+1
  417. // if it does not exist yet as well as remove the DAG for epoch n-1
  418. // the loop quits if autodagquit channel is closed, it can safely restart and
  419. // stop any number of times.
  420. // For any more sophisticated pattern of DAG generation, use CLI subcommand
  421. // makedag
  422. func (self *Ethereum) StartAutoDAG() {
  423. if self.autodagquit != nil {
  424. return // already started
  425. }
  426. go func() {
  427. glog.V(logger.Info).Infof("Automatic pregeneration of ethash DAG ON (ethash dir: %s)", ethash.DefaultDir)
  428. var nextEpoch uint64
  429. timer := time.After(0)
  430. self.autodagquit = make(chan bool)
  431. for {
  432. select {
  433. case <-timer:
  434. glog.V(logger.Info).Infof("checking DAG (ethash dir: %s)", ethash.DefaultDir)
  435. currentBlock := self.BlockChain().CurrentBlock().NumberU64()
  436. thisEpoch := currentBlock / epochLength
  437. if nextEpoch <= thisEpoch {
  438. if currentBlock%epochLength > autoDAGepochHeight {
  439. if thisEpoch > 0 {
  440. previousDag, previousDagFull := dagFiles(thisEpoch - 1)
  441. os.Remove(filepath.Join(ethash.DefaultDir, previousDag))
  442. os.Remove(filepath.Join(ethash.DefaultDir, previousDagFull))
  443. glog.V(logger.Info).Infof("removed DAG for epoch %d (%s)", thisEpoch-1, previousDag)
  444. }
  445. nextEpoch = thisEpoch + 1
  446. dag, _ := dagFiles(nextEpoch)
  447. if _, err := os.Stat(dag); os.IsNotExist(err) {
  448. glog.V(logger.Info).Infof("Pregenerating DAG for epoch %d (%s)", nextEpoch, dag)
  449. err := ethash.MakeDAG(nextEpoch*epochLength, "") // "" -> ethash.DefaultDir
  450. if err != nil {
  451. glog.V(logger.Error).Infof("Error generating DAG for epoch %d (%s)", nextEpoch, dag)
  452. return
  453. }
  454. } else {
  455. glog.V(logger.Error).Infof("DAG for epoch %d (%s)", nextEpoch, dag)
  456. }
  457. }
  458. }
  459. timer = time.After(autoDAGcheckInterval)
  460. case <-self.autodagquit:
  461. return
  462. }
  463. }
  464. }()
  465. }
  466. // stopAutoDAG stops automatic DAG pregeneration by quitting the loop
  467. func (self *Ethereum) StopAutoDAG() {
  468. if self.autodagquit != nil {
  469. close(self.autodagquit)
  470. self.autodagquit = nil
  471. }
  472. glog.V(logger.Info).Infof("Automatic pregeneration of ethash DAG OFF (ethash dir: %s)", ethash.DefaultDir)
  473. }
  474. // HTTPClient returns the light http client used for fetching offchain docs
  475. // (natspec, source for verification)
  476. func (self *Ethereum) HTTPClient() *httpclient.HTTPClient {
  477. return self.httpclient
  478. }
  479. // dagFiles(epoch) returns the two alternative DAG filenames (not a path)
  480. // 1) <revision>-<hex(seedhash[8])> 2) full-R<revision>-<hex(seedhash[8])>
  481. func dagFiles(epoch uint64) (string, string) {
  482. seedHash, _ := ethash.GetSeedHash(epoch * epochLength)
  483. dag := fmt.Sprintf("full-R%d-%x", ethashRevision, seedHash[:8])
  484. return dag, "full-R" + dag
  485. }