github.com/nitinawathare/ethereumassignment3@v0.0.0-20211021213010-f07344c2b868/go-ethereum/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/ethereum/go-ethereum/accounts" 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/common/hexutil" 31 "github.com/ethereum/go-ethereum/consensus" 32 "github.com/ethereum/go-ethereum/consensus/clique" 33 "github.com/ethereum/go-ethereum/consensus/ethash" 34 "github.com/ethereum/go-ethereum/core" 35 "github.com/ethereum/go-ethereum/core/bloombits" 36 "github.com/ethereum/go-ethereum/core/rawdb" 37 "github.com/ethereum/go-ethereum/core/types" 38 "github.com/ethereum/go-ethereum/core/vm" 39 "github.com/ethereum/go-ethereum/eth/downloader" 40 "github.com/ethereum/go-ethereum/eth/filters" 41 "github.com/ethereum/go-ethereum/eth/gasprice" 42 "github.com/ethereum/go-ethereum/ethdb" 43 "github.com/ethereum/go-ethereum/event" 44 "github.com/ethereum/go-ethereum/internal/ethapi" 45 "github.com/ethereum/go-ethereum/log" 46 "github.com/ethereum/go-ethereum/miner" 47 "github.com/ethereum/go-ethereum/node" 48 "github.com/ethereum/go-ethereum/p2p" 49 "github.com/ethereum/go-ethereum/params" 50 "github.com/ethereum/go-ethereum/rlp" 51 "github.com/ethereum/go-ethereum/rpc" 52 ) 53 54 type LesServer interface { 55 Start(srvr *p2p.Server) 56 Stop() 57 APIs() []rpc.API 58 Protocols() []p2p.Protocol 59 SetBloomBitsIndexer(bbIndexer *core.ChainIndexer) 60 } 61 62 // Ethereum implements the Ethereum full node service. 63 type Ethereum struct { 64 config *Config 65 66 // Channel for shutting down the service 67 shutdownChan chan bool // Channel for shutting down the Ethereum 68 69 // Handlers 70 txPool *core.TxPool 71 blockchain *core.BlockChain 72 protocolManager *ProtocolManager 73 lesServer LesServer 74 75 // DB interfaces 76 chainDb ethdb.Database // Block chain database 77 78 eventMux *event.TypeMux 79 engine consensus.Engine 80 accountManager *accounts.Manager 81 82 bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests 83 bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports 84 85 APIBackend *EthAPIBackend 86 87 miner *miner.Miner 88 gasPrice *big.Int 89 etherbase common.Address 90 91 networkID uint64 92 interArrival float64 93 hashPower float64 94 behavior uint64 95 netRPCService *ethapi.PublicNetAPI 96 97 lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase) 98 } 99 100 func (s *Ethereum) AddLesServer(ls LesServer) { 101 s.lesServer = ls 102 ls.SetBloomBitsIndexer(s.bloomIndexer) 103 } 104 105 // New creates a new Ethereum object (including the 106 // initialisation of the common Ethereum object) 107 func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { 108 // Ensure configuration values are compatible and sane 109 if config.SyncMode == downloader.LightSync { 110 return nil, errors.New("can't run eth.Ethereum in light sync mode, use les.LightEthereum") 111 } 112 if !config.SyncMode.IsValid() { 113 return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) 114 } 115 if config.MinerGasPrice == nil || config.MinerGasPrice.Cmp(common.Big0) <= 0 { 116 log.Warn("Sanitizing invalid miner gas price", "provided", config.MinerGasPrice, "updated", DefaultConfig.MinerGasPrice) 117 config.MinerGasPrice = new(big.Int).Set(DefaultConfig.MinerGasPrice) 118 } 119 if config.NoPruning && config.TrieDirtyCache > 0 { 120 config.TrieCleanCache += config.TrieDirtyCache 121 config.TrieDirtyCache = 0 122 } 123 log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024) 124 125 // Assemble the Ethereum object 126 chainDb, err := ctx.OpenDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles, "eth/db/chaindata/") 127 if err != nil { 128 return nil, err 129 } 130 chainConfig, genesisHash, _, _, _, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.ConstantinopleOverride) 131 if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { 132 return nil, genesisErr 133 } 134 log.Info("Initialised chain configuration", "config", chainConfig) 135 136 eth := &Ethereum{ 137 config: config, 138 chainDb: chainDb, 139 eventMux: ctx.EventMux, 140 accountManager: ctx.AccountManager, 141 engine: CreateConsensusEngine(ctx, chainConfig, &config.Ethash, config.MinerNotify, config.MinerNoverify, chainDb), 142 shutdownChan: make(chan bool), 143 interArrival: config.InterArrival, 144 hashPower: config.HashPower, 145 behavior: config.Behavior, 146 networkID: config.NetworkId, 147 gasPrice: config.MinerGasPrice, 148 etherbase: config.Etherbase, 149 bloomRequests: make(chan chan *bloombits.Retrieval), 150 bloomIndexer: NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms), 151 } 152 153 bcVersion := rawdb.ReadDatabaseVersion(chainDb) 154 var dbVer = "<nil>" 155 if bcVersion != nil { 156 dbVer = fmt.Sprintf("%d", *bcVersion) 157 } 158 log.Info("Initialising Ethereum protocol", "versions", ProtocolVersions, "network", config.NetworkId, "dbversion", dbVer) 159 160 if !config.SkipBcVersionCheck { 161 if bcVersion != nil && *bcVersion > core.BlockChainVersion { 162 return nil, fmt.Errorf("database version is v%d, Geth %s only supports v%d", *bcVersion, params.VersionWithMeta, core.BlockChainVersion) 163 } else if bcVersion == nil || *bcVersion < core.BlockChainVersion { 164 log.Warn("Upgrade blockchain database version", "from", dbVer, "to", core.BlockChainVersion) 165 rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion) 166 } 167 } 168 var ( 169 vmConfig = vm.Config{ 170 EnablePreimageRecording: config.EnablePreimageRecording, 171 EWASMInterpreter: config.EWASMInterpreter, 172 EVMInterpreter: config.EVMInterpreter, 173 } 174 cacheConfig = &core.CacheConfig{ 175 TrieCleanLimit: config.TrieCleanCache, 176 TrieCleanNoPrefetch: config.NoPrefetch, 177 TrieDirtyLimit: config.TrieDirtyCache, 178 TrieDirtyDisabled: config.NoPruning, 179 TrieTimeLimit: config.TrieTimeout, 180 } 181 ) 182 eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, config.HashPower, config.InterArrival, config.Behavior, eth.engine, vmConfig, eth.shouldPreserve) 183 if err != nil { 184 return nil, err 185 } 186 // Rewind the chain in case of an incompatible config upgrade. 187 if compat, ok := genesisErr.(*params.ConfigCompatError); ok { 188 log.Warn("Rewinding chain to upgrade configuration", "err", compat) 189 eth.blockchain.SetHead(compat.RewindTo) 190 rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) 191 } 192 eth.bloomIndexer.Start(eth.blockchain) 193 194 if config.TxPool.Journal != "" { 195 config.TxPool.Journal = ctx.ResolvePath(config.TxPool.Journal) 196 } 197 eth.txPool = core.NewTxPool(config.TxPool, chainConfig, eth.blockchain) 198 199 if eth.protocolManager, err = NewProtocolManager(chainConfig, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb, config.Whitelist); err != nil { 200 return nil, err 201 } 202 203 eth.miner = miner.New(eth, chainConfig, eth.EventMux(), eth.engine, config.MinerRecommit, config.MinerGasFloor, config.MinerGasCeil, eth.isLocalBlock) 204 eth.miner.SetExtra(makeExtraData(config.MinerExtraData)) 205 206 eth.APIBackend = &EthAPIBackend{ctx.ExtRPCEnabled(), eth, nil} 207 gpoParams := config.GPO 208 if gpoParams.Default == nil { 209 gpoParams.Default = config.MinerGasPrice 210 } 211 eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams) 212 213 return eth, nil 214 } 215 216 func makeExtraData(extra []byte) []byte { 217 if len(extra) == 0 { 218 // create default extradata 219 extra, _ = rlp.EncodeToBytes([]interface{}{ 220 uint(params.VersionMajor<<16 | params.VersionMinor<<8 | params.VersionPatch), 221 "geth", 222 runtime.Version(), 223 runtime.GOOS, 224 }) 225 } 226 if uint64(len(extra)) > params.MaximumExtraDataSize { 227 log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", params.MaximumExtraDataSize) 228 extra = nil 229 } 230 return extra 231 } 232 233 // CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service 234 func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database) consensus.Engine { 235 // If proof-of-authority is requested, set it up 236 if chainConfig.Clique != nil { 237 return clique.New(chainConfig.Clique, db) 238 } 239 // Otherwise assume proof-of-work 240 switch config.PowMode { 241 case ethash.ModeFake: 242 log.Warn("Ethash used in fake mode") 243 return ethash.NewFaker() 244 case ethash.ModeTest: 245 log.Warn("Ethash used in test mode") 246 return ethash.NewTester(nil, noverify) 247 case ethash.ModeShared: 248 log.Warn("Ethash used in shared mode") 249 return ethash.NewShared() 250 default: 251 engine := ethash.New(ethash.Config{ 252 CacheDir: ctx.ResolvePath(config.CacheDir), 253 CachesInMem: config.CachesInMem, 254 CachesOnDisk: config.CachesOnDisk, 255 DatasetDir: config.DatasetDir, 256 DatasetsInMem: config.DatasetsInMem, 257 DatasetsOnDisk: config.DatasetsOnDisk, 258 }, notify, noverify) 259 engine.SetThreads(-1) // Disable CPU mining 260 return engine 261 } 262 } 263 264 // APIs return the collection of RPC services the ethereum package offers. 265 // NOTE, some of these services probably need to be moved to somewhere else. 266 func (s *Ethereum) APIs() []rpc.API { 267 apis := ethapi.GetAPIs(s.APIBackend) 268 269 // Append any APIs exposed explicitly by the les server 270 if s.lesServer != nil { 271 apis = append(apis, s.lesServer.APIs()...) 272 } 273 // Append any APIs exposed explicitly by the consensus engine 274 apis = append(apis, s.engine.APIs(s.BlockChain())...) 275 276 // Append all the local APIs and return 277 return append(apis, []rpc.API{ 278 { 279 Namespace: "eth", 280 Version: "1.0", 281 Service: NewPublicEthereumAPI(s), 282 Public: true, 283 }, { 284 Namespace: "eth", 285 Version: "1.0", 286 Service: NewPublicMinerAPI(s), 287 Public: true, 288 }, { 289 Namespace: "eth", 290 Version: "1.0", 291 Service: downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux), 292 Public: true, 293 }, { 294 Namespace: "miner", 295 Version: "1.0", 296 Service: NewPrivateMinerAPI(s), 297 Public: false, 298 }, { 299 Namespace: "eth", 300 Version: "1.0", 301 Service: filters.NewPublicFilterAPI(s.APIBackend, false), 302 Public: true, 303 }, { 304 Namespace: "admin", 305 Version: "1.0", 306 Service: NewPrivateAdminAPI(s), 307 }, { 308 Namespace: "debug", 309 Version: "1.0", 310 Service: NewPublicDebugAPI(s), 311 Public: true, 312 }, { 313 Namespace: "debug", 314 Version: "1.0", 315 Service: NewPrivateDebugAPI(s), 316 }, { 317 Namespace: "net", 318 Version: "1.0", 319 Service: s.netRPCService, 320 Public: true, 321 }, 322 }...) 323 } 324 325 func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) { 326 s.blockchain.ResetWithGenesisBlock(gb) 327 } 328 329 func (s *Ethereum) Etherbase() (eb common.Address, err error) { 330 s.lock.RLock() 331 etherbase := s.etherbase 332 s.lock.RUnlock() 333 334 if etherbase != (common.Address{}) { 335 return etherbase, nil 336 } 337 if wallets := s.AccountManager().Wallets(); len(wallets) > 0 { 338 if accounts := wallets[0].Accounts(); len(accounts) > 0 { 339 etherbase := accounts[0].Address 340 341 s.lock.Lock() 342 s.etherbase = etherbase 343 s.lock.Unlock() 344 345 log.Info("Etherbase automatically configured", "address", etherbase) 346 return etherbase, nil 347 } 348 } 349 return common.Address{}, fmt.Errorf("etherbase must be explicitly specified") 350 } 351 352 // isLocalBlock checks whether the specified block is mined 353 // by local miner accounts. 354 // 355 // We regard two types of accounts as local miner account: etherbase 356 // and accounts specified via `txpool.locals` flag. 357 func (s *Ethereum) isLocalBlock(block *types.Block) bool { 358 author, err := s.engine.Author(block.Header()) 359 if err != nil { 360 log.Warn("Failed to retrieve block author", "number", block.NumberU64(), "hash", block.Hash(), "err", err) 361 return false 362 } 363 // Check whether the given address is etherbase. 364 s.lock.RLock() 365 etherbase := s.etherbase 366 s.lock.RUnlock() 367 if author == etherbase { 368 return true 369 } 370 // Check whether the given address is specified by `txpool.local` 371 // CLI flag. 372 for _, account := range s.config.TxPool.Locals { 373 if account == author { 374 return true 375 } 376 } 377 return false 378 } 379 380 // shouldPreserve checks whether we should preserve the given block 381 // during the chain reorg depending on whether the author of block 382 // is a local account. 383 func (s *Ethereum) shouldPreserve(block *types.Block) bool { 384 // The reason we need to disable the self-reorg preserving for clique 385 // is it can be probable to introduce a deadlock. 386 // 387 // e.g. If there are 7 available signers 388 // 389 // r1 A 390 // r2 B 391 // r3 C 392 // r4 D 393 // r5 A [X] F G 394 // r6 [X] 395 // 396 // In the round5, the inturn signer E is offline, so the worst case 397 // is A, F and G sign the block of round5 and reject the block of opponents 398 // and in the round6, the last available signer B is offline, the whole 399 // network is stuck. 400 if _, ok := s.engine.(*clique.Clique); ok { 401 return false 402 } 403 return s.isLocalBlock(block) 404 } 405 406 // SetEtherbase sets the mining reward address. 407 func (s *Ethereum) SetEtherbase(etherbase common.Address) { 408 s.lock.Lock() 409 s.etherbase = etherbase 410 s.lock.Unlock() 411 412 s.miner.SetEtherbase(etherbase) 413 } 414 415 // StartMining starts the miner with the given number of CPU threads. If mining 416 // is already running, this method adjust the number of threads allowed to use 417 // and updates the minimum price required by the transaction pool. 418 func (s *Ethereum) StartMining(threads int) error { 419 // Update the thread count within the consensus engine 420 type threaded interface { 421 SetThreads(threads int) 422 } 423 if th, ok := s.engine.(threaded); ok { 424 log.Info("Updated mining threads", "threads", threads) 425 if threads == 0 { 426 threads = -1 // Disable the miner from within 427 } 428 th.SetThreads(threads) 429 } 430 // If the miner was not running, initialize it 431 if !s.IsMining() { 432 // Propagate the initial price point to the transaction pool 433 s.lock.RLock() 434 price := s.gasPrice 435 s.lock.RUnlock() 436 s.txPool.SetGasPrice(price) 437 438 // Configure the local mining address 439 eb, err := s.Etherbase() 440 if err != nil { 441 log.Error("Cannot start mining without etherbase", "err", err) 442 return fmt.Errorf("etherbase missing: %v", err) 443 } 444 if clique, ok := s.engine.(*clique.Clique); ok { 445 wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) 446 if wallet == nil || err != nil { 447 log.Error("Etherbase account unavailable locally", "err", err) 448 return fmt.Errorf("signer missing: %v", err) 449 } 450 clique.Authorize(eb, wallet.SignData) 451 } 452 // If mining is started, we can disable the transaction rejection mechanism 453 // introduced to speed sync times. 454 atomic.StoreUint32(&s.protocolManager.acceptTxs, 1) 455 456 go s.miner.Start(eb) 457 } 458 return nil 459 } 460 461 // StopMining terminates the miner, both at the consensus engine level as well as 462 // at the block creation level. 463 func (s *Ethereum) StopMining() { 464 // Update the thread count within the consensus engine 465 type threaded interface { 466 SetThreads(threads int) 467 } 468 if th, ok := s.engine.(threaded); ok { 469 th.SetThreads(-1) 470 } 471 // Stop the block creating itself 472 s.miner.Stop() 473 } 474 475 func (s *Ethereum) IsMining() bool { return s.miner.Mining() } 476 func (s *Ethereum) Miner() *miner.Miner { return s.miner } 477 478 func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } 479 func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } 480 func (s *Ethereum) TxPool() *core.TxPool { return s.txPool } 481 func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } 482 func (s *Ethereum) Engine() consensus.Engine { return s.engine } 483 func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } 484 func (s *Ethereum) IsListening() bool { return true } // Always listening 485 func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) } 486 func (s *Ethereum) InterArrival() float64 { return s.interArrival } 487 func (s *Ethereum) HashPower() float64 { return s.hashPower } 488 func (s *Ethereum) Behavior() uint64 { return s.behavior } 489 func (s *Ethereum) NetVersion() uint64 { return s.networkID } 490 func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader } 491 492 // Protocols implements node.Service, returning all the currently configured 493 // network protocols to start. 494 func (s *Ethereum) Protocols() []p2p.Protocol { 495 if s.lesServer == nil { 496 return s.protocolManager.SubProtocols 497 } 498 return append(s.protocolManager.SubProtocols, s.lesServer.Protocols()...) 499 } 500 501 // Start implements node.Service, starting all internal goroutines needed by the 502 // Ethereum protocol implementation. 503 func (s *Ethereum) Start(srvr *p2p.Server) error { 504 // Start the bloom bits servicing goroutines 505 s.startBloomHandlers(params.BloomBitsBlocks) 506 507 // Start the RPC service 508 s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.NetVersion()) 509 510 // Figure out a max peers count based on the server limits 511 maxPeers := srvr.MaxPeers 512 if s.config.LightServ > 0 { 513 if s.config.LightPeers >= srvr.MaxPeers { 514 return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, srvr.MaxPeers) 515 } 516 maxPeers -= s.config.LightPeers 517 } 518 // Start the networking layer and the light server if requested 519 s.protocolManager.Start(maxPeers) 520 if s.lesServer != nil { 521 s.lesServer.Start(srvr) 522 } 523 return nil 524 } 525 526 // Stop implements node.Service, terminating all internal goroutines used by the 527 // Ethereum protocol. 528 func (s *Ethereum) Stop() error { 529 s.bloomIndexer.Close() 530 s.blockchain.Stop() 531 s.engine.Close() 532 s.protocolManager.Stop() 533 if s.lesServer != nil { 534 s.lesServer.Stop() 535 } 536 s.txPool.Stop() 537 s.miner.Stop() 538 s.eventMux.Stop() 539 540 s.chainDb.Close() 541 close(s.shutdownChan) 542 return nil 543 }