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