github.com/halybang/go-ethereum@v1.0.5-0.20180325041310-3b262bc1367c/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 "runtime" 25 "sync" 26 "sync/atomic" 27 28 "github.com/wanchain/go-wanchain/accounts" 29 "github.com/wanchain/go-wanchain/common" 30 "github.com/wanchain/go-wanchain/common/hexutil" 31 "github.com/wanchain/go-wanchain/consensus" 32 "github.com/wanchain/go-wanchain/consensus/clique" 33 "github.com/wanchain/go-wanchain/consensus/ethash" 34 "github.com/wanchain/go-wanchain/core" 35 "github.com/wanchain/go-wanchain/core/bloombits" 36 "github.com/wanchain/go-wanchain/core/types" 37 "github.com/wanchain/go-wanchain/core/vm" 38 "github.com/wanchain/go-wanchain/eth/downloader" 39 "github.com/wanchain/go-wanchain/eth/filters" 40 "github.com/wanchain/go-wanchain/eth/gasprice" 41 "github.com/wanchain/go-wanchain/ethdb" 42 "github.com/wanchain/go-wanchain/event" 43 "github.com/wanchain/go-wanchain/internal/ethapi" 44 "github.com/wanchain/go-wanchain/log" 45 "github.com/wanchain/go-wanchain/miner" 46 "github.com/wanchain/go-wanchain/node" 47 "github.com/wanchain/go-wanchain/p2p" 48 "github.com/wanchain/go-wanchain/params" 49 "github.com/wanchain/go-wanchain/rlp" 50 "github.com/wanchain/go-wanchain/rpc" 51 ) 52 53 type LesServer interface { 54 Start(srvr *p2p.Server) 55 Stop() 56 Protocols() []p2p.Protocol 57 } 58 59 // Ethereum implements the Ethereum full node service. 60 type Ethereum struct { 61 config *Config 62 chainConfig *params.ChainConfig 63 64 // Channel for shutting down the service 65 shutdownChan chan bool // Channel for shutting down the ethereum 66 stopDbUpgrade func() error // stop chain db sequential key upgrade 67 68 // Handlers 69 txPool *core.TxPool 70 blockchain *core.BlockChain 71 protocolManager *ProtocolManager 72 lesServer LesServer 73 74 // DB interfaces 75 chainDb ethdb.Database // Block chain database 76 77 eventMux *event.TypeMux 78 engine consensus.Engine 79 accountManager *accounts.Manager 80 81 bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests 82 bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports 83 84 ApiBackend *EthApiBackend 85 86 miner *miner.Miner 87 gasPrice *big.Int 88 etherbase common.Address 89 90 networkId uint64 91 netRPCService *ethapi.PublicNetAPI 92 93 lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase) 94 } 95 96 func (s *Ethereum) AddLesServer(ls LesServer) { 97 s.lesServer = ls 98 } 99 100 // New creates a new Ethereum object (including the 101 // initialisation of the common Ethereum object) 102 func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { 103 if config.SyncMode == downloader.LightSync { 104 return nil, errors.New("can't run eth.Ethereum in light sync mode, use les.LightEthereum") 105 } 106 if !config.SyncMode.IsValid() { 107 return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) 108 } 109 chainDb, err := CreateDB(ctx, config, "chaindata") 110 if err != nil { 111 return nil, err 112 } 113 stopDbUpgrade := upgradeDeduplicateData(chainDb) 114 chainConfig, genesisHash, genesisErr := core.SetupGenesisBlock(chainDb, config.Genesis) 115 if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { 116 return nil, genesisErr 117 } 118 log.Info("Initialised chain configuration", "config", chainConfig) 119 120 eth := &Ethereum{ 121 config: config, 122 chainDb: chainDb, 123 chainConfig: chainConfig, 124 eventMux: ctx.EventMux, 125 accountManager: ctx.AccountManager, 126 engine: CreateConsensusEngine(ctx, config, chainConfig, chainDb), 127 shutdownChan: make(chan bool), 128 stopDbUpgrade: stopDbUpgrade, 129 networkId: config.NetworkId, 130 gasPrice: config.GasPrice, 131 etherbase: config.Etherbase, 132 bloomRequests: make(chan chan *bloombits.Retrieval), 133 bloomIndexer: NewBloomIndexer(chainDb, params.BloomBitsBlocks), 134 } 135 136 log.Info("Initialising Wanchain protocol", "versions", ProtocolVersions, "network", config.NetworkId) 137 138 if !config.SkipBcVersionCheck { 139 bcVersion := core.GetBlockChainVersion(chainDb) 140 if bcVersion != core.BlockChainVersion && bcVersion != 0 { 141 return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d). Run geth upgradedb.\n", bcVersion, core.BlockChainVersion) 142 } 143 core.WriteBlockChainVersion(chainDb, core.BlockChainVersion) 144 } 145 146 vmConfig := vm.Config{EnablePreimageRecording: config.EnablePreimageRecording} 147 eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.engine, vmConfig) 148 if err != nil { 149 return nil, err 150 } 151 // Rewind the chain in case of an incompatible config upgrade. 152 if compat, ok := genesisErr.(*params.ConfigCompatError); ok { 153 log.Warn("Rewinding chain to upgrade configuration", "err", compat) 154 eth.blockchain.SetHead(compat.RewindTo) 155 core.WriteChainConfig(chainDb, genesisHash, chainConfig) 156 } 157 eth.bloomIndexer.Start(eth.blockchain.CurrentHeader(), eth.blockchain.SubscribeChainEvent) 158 159 if config.TxPool.Journal != "" { 160 config.TxPool.Journal = ctx.ResolvePath(config.TxPool.Journal) 161 } 162 eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain) 163 164 if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb); err != nil { 165 return nil, err 166 } 167 eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine) 168 eth.miner.SetExtra(makeExtraData(config.ExtraData)) 169 170 eth.ApiBackend = &EthApiBackend{eth, nil} 171 gpoParams := config.GPO 172 if gpoParams.Default == nil { 173 gpoParams.Default = config.GasPrice 174 } 175 eth.ApiBackend.gpo = gasprice.NewOracle(eth.ApiBackend, gpoParams) 176 177 return eth, nil 178 } 179 180 func makeExtraData(extra []byte) []byte { 181 if len(extra) == 0 { 182 // create default extradata 183 extra, _ = rlp.EncodeToBytes([]interface{}{ 184 uint(params.VersionMajor<<16 | params.VersionMinor<<8 | params.VersionPatch), 185 "geth", 186 runtime.Version(), 187 runtime.GOOS, 188 }) 189 } 190 if uint64(len(extra)) > params.MaximumExtraDataSize { 191 log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", params.MaximumExtraDataSize) 192 extra = nil 193 } 194 return extra 195 } 196 197 // CreateDB creates the chain database. 198 func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Database, error) { 199 db, err := ctx.OpenDatabase(name, config.DatabaseCache, config.DatabaseHandles) 200 if err != nil { 201 return nil, err 202 } 203 if db, ok := db.(*ethdb.LDBDatabase); ok { 204 db.Meter("eth/db/chaindata/") 205 } 206 return db, nil 207 } 208 209 // CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service 210 func CreateConsensusEngine(ctx *node.ServiceContext, config *Config, chainConfig *params.ChainConfig, db ethdb.Database) consensus.Engine { 211 // If proof-of-authority is requested, set it up 212 if chainConfig.Clique != nil { 213 return clique.New(chainConfig.Clique, db) 214 } 215 if chainConfig.Pluto != nil { 216 var cliqueCfg params.CliqueConfig 217 chainConfig.Clique = &cliqueCfg 218 chainConfig.Clique.Period = chainConfig.Pluto.Period 219 chainConfig.Clique.Epoch = chainConfig.Pluto.Epoch 220 return clique.New(chainConfig.Clique, db) 221 } 222 // Otherwise assume proof-of-work 223 switch { 224 case config.PowFake: 225 log.Warn("Ethash used in fake mode") 226 return ethash.NewFaker(db) 227 case config.PowTest: 228 log.Warn("Ethash used in test mode") 229 return ethash.NewTester(db) 230 case config.PowShared: 231 log.Warn("Ethash used in shared mode") 232 return ethash.NewShared() 233 default: 234 engine := ethash.New(ctx.ResolvePath(config.EthashCacheDir), config.EthashCachesInMem, config.EthashCachesOnDisk, 235 config.EthashDatasetDir, config.EthashDatasetsInMem, config.EthashDatasetsOnDisk, db) 236 engine.SetThreads(-1) // Disable CPU mining 237 return engine 238 } 239 } 240 241 // APIs returns the collection of RPC services the ethereum package offers. 242 // NOTE, some of these services probably need to be moved to somewhere else. 243 func (s *Ethereum) APIs() []rpc.API { 244 apis := ethapi.GetAPIs(s.ApiBackend) 245 246 // Append any APIs exposed explicitly by the consensus engine 247 apis = append(apis, s.engine.APIs(s.BlockChain())...) 248 249 // Append all the local APIs and return 250 return append(apis, []rpc.API{ 251 { 252 Namespace: "eth", 253 Version: "1.0", 254 Service: NewPublicEthereumAPI(s), 255 Public: true, 256 }, { 257 Namespace: "eth", 258 Version: "1.0", 259 Service: NewPublicMinerAPI(s), 260 Public: true, 261 }, { 262 Namespace: "eth", 263 Version: "1.0", 264 Service: downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux), 265 Public: true, 266 }, { 267 Namespace: "miner", 268 Version: "1.0", 269 Service: NewPrivateMinerAPI(s), 270 Public: false, 271 }, { 272 Namespace: "eth", 273 Version: "1.0", 274 Service: filters.NewPublicFilterAPI(s.ApiBackend, false), 275 Public: true, 276 }, { 277 Namespace: "admin", 278 Version: "1.0", 279 Service: NewPrivateAdminAPI(s), 280 }, { 281 Namespace: "debug", 282 Version: "1.0", 283 Service: NewPublicDebugAPI(s), 284 Public: true, 285 }, { 286 Namespace: "debug", 287 Version: "1.0", 288 Service: NewPrivateDebugAPI(s.chainConfig, s), 289 }, { 290 Namespace: "net", 291 Version: "1.0", 292 Service: s.netRPCService, 293 Public: true, 294 }, 295 }...) 296 } 297 298 func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) { 299 s.blockchain.ResetWithGenesisBlock(gb) 300 } 301 302 func (s *Ethereum) Etherbase() (eb common.Address, err error) { 303 s.lock.RLock() 304 etherbase := s.etherbase 305 s.lock.RUnlock() 306 307 if etherbase != (common.Address{}) { 308 return etherbase, nil 309 } 310 if wallets := s.AccountManager().Wallets(); len(wallets) > 0 { 311 if accounts := wallets[0].Accounts(); len(accounts) > 0 { 312 return accounts[0].Address, nil 313 } 314 } 315 return common.Address{}, fmt.Errorf("etherbase address must be explicitly specified") 316 } 317 318 // set in js console via admin interface or wrapper from cli flags 319 func (self *Ethereum) SetEtherbase(etherbase common.Address) { 320 self.lock.Lock() 321 self.etherbase = etherbase 322 self.lock.Unlock() 323 324 self.miner.SetEtherbase(etherbase) 325 } 326 327 func (s *Ethereum) StartMining(local bool) error { 328 eb, err := s.Etherbase() 329 if err != nil { 330 log.Error("Cannot start mining without etherbase", "err", err) 331 return fmt.Errorf("etherbase missing: %v", err) 332 } 333 if clique, ok := s.engine.(*clique.Clique); ok { 334 wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) 335 if wallet == nil || err != nil { 336 log.Error("Etherbase account unavailable locally", "err", err) 337 return fmt.Errorf("signer missing: %v", err) 338 } 339 clique.Authorize(eb, wallet.SignHash) 340 } 341 342 if ethash, ok := s.engine.(*ethash.Ethash); ok { 343 wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) 344 if wallet == nil || err != nil { 345 log.Error("Etherbase account unavailable locally", "err", err) 346 return fmt.Errorf("singer missing: %v", err) 347 } 348 ethash.Authorize(eb, wallet.SignHash) 349 } 350 if local { 351 // If local (CPU) mining is started, we can disable the transaction rejection 352 // mechanism introduced to speed sync times. CPU mining on mainnet is ludicrous 353 // so noone will ever hit this path, whereas marking sync done on CPU mining 354 // will ensure that private networks work in single miner mode too. 355 atomic.StoreUint32(&s.protocolManager.acceptTxs, 1) 356 } 357 go s.miner.Start(eb) 358 return nil 359 } 360 361 func (s *Ethereum) StopMining() { s.miner.Stop() } 362 func (s *Ethereum) IsMining() bool { return s.miner.Mining() } 363 func (s *Ethereum) Miner() *miner.Miner { return s.miner } 364 365 func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } 366 func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } 367 func (s *Ethereum) TxPool() *core.TxPool { return s.txPool } 368 func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } 369 func (s *Ethereum) Engine() consensus.Engine { return s.engine } 370 func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } 371 func (s *Ethereum) IsListening() bool { return true } // Always listening 372 func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) } 373 func (s *Ethereum) NetVersion() uint64 { return s.networkId } 374 func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader } 375 376 // Protocols implements node.Service, returning all the currently configured 377 // network protocols to start. 378 func (s *Ethereum) Protocols() []p2p.Protocol { 379 if s.lesServer == nil { 380 return s.protocolManager.SubProtocols 381 } 382 return append(s.protocolManager.SubProtocols, s.lesServer.Protocols()...) 383 } 384 385 // Start implements node.Service, starting all internal goroutines needed by the 386 // Ethereum protocol implementation. 387 func (s *Ethereum) Start(srvr *p2p.Server) error { 388 // Start the bloom bits servicing goroutines 389 s.startBloomHandlers() 390 391 // Start the RPC service 392 s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.NetVersion()) 393 394 // Figure out a max peers count based on the server limits 395 maxPeers := srvr.MaxPeers 396 if s.config.LightServ > 0 { 397 maxPeers -= s.config.LightPeers 398 if maxPeers < srvr.MaxPeers/2 { 399 maxPeers = srvr.MaxPeers / 2 400 } 401 } 402 // Start the networking layer and the light server if requested 403 s.protocolManager.Start(maxPeers) 404 if s.lesServer != nil { 405 s.lesServer.Start(srvr) 406 } 407 return nil 408 } 409 410 // Stop implements node.Service, terminating all internal goroutines used by the 411 // Ethereum protocol. 412 func (s *Ethereum) Stop() error { 413 if s.stopDbUpgrade != nil { 414 s.stopDbUpgrade() 415 } 416 s.bloomIndexer.Close() 417 s.blockchain.Stop() 418 s.protocolManager.Stop() 419 if s.lesServer != nil { 420 s.lesServer.Stop() 421 } 422 s.txPool.Stop() 423 s.miner.Stop() 424 s.eventMux.Stop() 425 426 s.chainDb.Close() 427 close(s.shutdownChan) 428 429 return nil 430 }