github.com/phillinzzz/newBsc@v1.1.6/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 "time" 28 29 "github.com/phillinzzz/newBsc/accounts" 30 "github.com/phillinzzz/newBsc/common" 31 "github.com/phillinzzz/newBsc/common/hexutil" 32 "github.com/phillinzzz/newBsc/consensus" 33 "github.com/phillinzzz/newBsc/consensus/clique" 34 "github.com/phillinzzz/newBsc/consensus/parlia" 35 "github.com/phillinzzz/newBsc/core" 36 "github.com/phillinzzz/newBsc/core/bloombits" 37 "github.com/phillinzzz/newBsc/core/rawdb" 38 "github.com/phillinzzz/newBsc/core/state/pruner" 39 "github.com/phillinzzz/newBsc/core/types" 40 "github.com/phillinzzz/newBsc/core/vm" 41 "github.com/phillinzzz/newBsc/eth/downloader" 42 "github.com/phillinzzz/newBsc/eth/ethconfig" 43 "github.com/phillinzzz/newBsc/eth/filters" 44 "github.com/phillinzzz/newBsc/eth/gasprice" 45 "github.com/phillinzzz/newBsc/eth/protocols/diff" 46 "github.com/phillinzzz/newBsc/eth/protocols/eth" 47 "github.com/phillinzzz/newBsc/eth/protocols/snap" 48 "github.com/phillinzzz/newBsc/ethdb" 49 "github.com/phillinzzz/newBsc/event" 50 "github.com/phillinzzz/newBsc/internal/ethapi" 51 "github.com/phillinzzz/newBsc/log" 52 "github.com/phillinzzz/newBsc/miner" 53 "github.com/phillinzzz/newBsc/node" 54 "github.com/phillinzzz/newBsc/p2p" 55 "github.com/phillinzzz/newBsc/p2p/dnsdisc" 56 "github.com/phillinzzz/newBsc/p2p/enode" 57 "github.com/phillinzzz/newBsc/params" 58 "github.com/phillinzzz/newBsc/rlp" 59 "github.com/phillinzzz/newBsc/rpc" 60 ) 61 62 // Config contains the configuration options of the ETH protocol. 63 // Deprecated: use ethconfig.Config instead. 64 type Config = ethconfig.Config 65 66 // Ethereum implements the Ethereum full node service. 67 type Ethereum struct { 68 config *ethconfig.Config 69 70 // Handlers 71 txPool *core.TxPool 72 blockchain *core.BlockChain 73 handler *handler 74 ethDialCandidates enode.Iterator 75 snapDialCandidates enode.Iterator 76 77 // DB interfaces 78 chainDb ethdb.Database // Block chain database 79 80 eventMux *event.TypeMux 81 engine consensus.Engine 82 accountManager *accounts.Manager 83 84 bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests 85 bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports 86 closeBloomHandler chan struct{} 87 88 APIBackend *EthAPIBackend 89 90 miner *miner.Miner 91 gasPrice *big.Int 92 etherbase common.Address 93 94 networkID uint64 95 netRPCService *ethapi.PublicNetAPI 96 97 p2pServer *p2p.Server 98 99 lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase) 100 } 101 102 // New creates a new Ethereum object (including the 103 // initialisation of the common Ethereum object) 104 func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { 105 // Ensure configuration values are compatible and sane 106 if config.SyncMode == downloader.LightSync { 107 return nil, errors.New("can't run eth.Ethereum in light sync mode, use les.LightEthereum") 108 } 109 if !config.SyncMode.IsValid() { 110 return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) 111 } 112 if config.Miner.GasPrice == nil || config.Miner.GasPrice.Cmp(common.Big0) <= 0 { 113 log.Warn("Sanitizing invalid miner gas price", "provided", config.Miner.GasPrice, "updated", ethconfig.Defaults.Miner.GasPrice) 114 config.Miner.GasPrice = new(big.Int).Set(ethconfig.Defaults.Miner.GasPrice) 115 } 116 if config.NoPruning && config.TrieDirtyCache > 0 { 117 if config.SnapshotCache > 0 { 118 config.TrieCleanCache += config.TrieDirtyCache * 3 / 5 119 config.SnapshotCache += config.TrieDirtyCache * 2 / 5 120 } else { 121 config.TrieCleanCache += config.TrieDirtyCache 122 } 123 config.TrieDirtyCache = 0 124 } 125 log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024) 126 127 // Transfer mining-related config to the ethash config. 128 ethashConfig := config.Ethash 129 ethashConfig.NotifyFull = config.Miner.NotifyFull 130 131 // Assemble the Ethereum object 132 chainDb, err := stack.OpenAndMergeDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles, 133 config.DatabaseFreezer, config.DatabaseDiff, "eth/db/chaindata/", false, config.PersistDiff) 134 if err != nil { 135 return nil, err 136 } 137 chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.OverrideBerlin) 138 if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { 139 return nil, genesisErr 140 } 141 log.Info("Initialised chain configuration", "config", chainConfig) 142 143 if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, stack.ResolvePath(config.TrieCleanCacheJournal), config.TriesInMemory); err != nil { 144 log.Error("Failed to recover state", "error", err) 145 } 146 eth := &Ethereum{ 147 config: config, 148 chainDb: chainDb, 149 eventMux: stack.EventMux(), 150 accountManager: stack.AccountManager(), 151 closeBloomHandler: make(chan struct{}), 152 networkID: config.NetworkId, 153 gasPrice: config.Miner.GasPrice, 154 etherbase: config.Miner.Etherbase, 155 bloomRequests: make(chan chan *bloombits.Retrieval), 156 bloomIndexer: core.NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms), 157 p2pServer: stack.Server(), 158 } 159 160 eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil} 161 if eth.APIBackend.allowUnprotectedTxs { 162 log.Info("Unprotected transactions allowed") 163 } 164 ethAPI := ethapi.NewPublicBlockChainAPI(eth.APIBackend) 165 eth.engine = ethconfig.CreateConsensusEngine(stack, chainConfig, ðashConfig, config.Miner.Notify, config.Miner.Noverify, chainDb, ethAPI, genesisHash) 166 167 bcVersion := rawdb.ReadDatabaseVersion(chainDb) 168 var dbVer = "<nil>" 169 if bcVersion != nil { 170 dbVer = fmt.Sprintf("%d", *bcVersion) 171 } 172 log.Info("Initialising Ethereum protocol", "network", config.NetworkId, "dbversion", dbVer) 173 174 if !config.SkipBcVersionCheck { 175 if bcVersion != nil && *bcVersion > core.BlockChainVersion { 176 return nil, fmt.Errorf("database version is v%d, Geth %s only supports v%d", *bcVersion, params.VersionWithMeta, core.BlockChainVersion) 177 } else if bcVersion == nil || *bcVersion < core.BlockChainVersion { 178 if bcVersion != nil { // only print warning on upgrade, not on init 179 log.Warn("Upgrade blockchain database version", "from", dbVer, "to", core.BlockChainVersion) 180 } 181 rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion) 182 } 183 } 184 var ( 185 vmConfig = vm.Config{ 186 EnablePreimageRecording: config.EnablePreimageRecording, 187 EWASMInterpreter: config.EWASMInterpreter, 188 EVMInterpreter: config.EVMInterpreter, 189 } 190 cacheConfig = &core.CacheConfig{ 191 TrieCleanLimit: config.TrieCleanCache, 192 TrieCleanJournal: stack.ResolvePath(config.TrieCleanCacheJournal), 193 TrieCleanRejournal: config.TrieCleanCacheRejournal, 194 TrieDirtyLimit: config.TrieDirtyCache, 195 TrieDirtyDisabled: config.NoPruning, 196 TrieTimeLimit: config.TrieTimeout, 197 SnapshotLimit: config.SnapshotCache, 198 TriesInMemory: config.TriesInMemory, 199 Preimages: config.Preimages, 200 } 201 ) 202 bcOps := make([]core.BlockChainOption, 0) 203 if config.DiffSync { 204 bcOps = append(bcOps, core.EnableLightProcessor) 205 } 206 if config.PersistDiff { 207 bcOps = append(bcOps, core.EnablePersistDiff(config.DiffBlock)) 208 } 209 eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve, &config.TxLookupLimit, bcOps...) 210 if err != nil { 211 return nil, err 212 } 213 // Rewind the chain in case of an incompatible config upgrade. 214 if compat, ok := genesisErr.(*params.ConfigCompatError); ok { 215 log.Warn("Rewinding chain to upgrade configuration", "err", compat) 216 eth.blockchain.SetHead(compat.RewindTo) 217 rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) 218 } 219 eth.bloomIndexer.Start(eth.blockchain) 220 221 if config.TxPool.Journal != "" { 222 config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal) 223 } 224 eth.txPool = core.NewTxPool(config.TxPool, chainConfig, eth.blockchain) 225 226 // Permit the downloader to use the trie cache allowance during fast sync 227 cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit 228 checkpoint := config.Checkpoint 229 if checkpoint == nil { 230 checkpoint = params.TrustedCheckpoints[genesisHash] 231 } 232 233 if eth.handler, err = newHandler(&handlerConfig{ 234 Database: chainDb, 235 Chain: eth.blockchain, 236 TxPool: eth.txPool, 237 Network: config.NetworkId, 238 Sync: config.SyncMode, 239 BloomCache: uint64(cacheLimit), 240 EventMux: eth.eventMux, 241 Checkpoint: checkpoint, 242 Whitelist: config.Whitelist, 243 DirectBroadcast: config.DirectBroadcast, 244 DiffSync: config.DiffSync, 245 DisablePeerTxBroadcast: config.DisablePeerTxBroadcast, 246 }); err != nil { 247 return nil, err 248 } 249 250 eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine, eth.isLocalBlock) 251 eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) 252 253 gpoParams := config.GPO 254 if gpoParams.Default == nil { 255 gpoParams.Default = config.Miner.GasPrice 256 } 257 eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams) 258 259 // Setup DNS discovery iterators. 260 dnsclient := dnsdisc.NewClient(dnsdisc.Config{}) 261 eth.ethDialCandidates, err = dnsclient.NewIterator(eth.config.EthDiscoveryURLs...) 262 if err != nil { 263 return nil, err 264 } 265 eth.snapDialCandidates, err = dnsclient.NewIterator(eth.config.SnapDiscoveryURLs...) 266 if err != nil { 267 return nil, err 268 } 269 270 // Start the RPC service 271 eth.netRPCService = ethapi.NewPublicNetAPI(eth.p2pServer, config.NetworkId) 272 273 // Register the backend on the node 274 stack.RegisterAPIs(eth.APIs()) 275 stack.RegisterProtocols(eth.Protocols()) 276 stack.RegisterLifecycle(eth) 277 // Check for unclean shutdown 278 if uncleanShutdowns, discards, err := rawdb.PushUncleanShutdownMarker(chainDb); err != nil { 279 log.Error("Could not update unclean-shutdown-marker list", "error", err) 280 } else { 281 if discards > 0 { 282 log.Warn("Old unclean shutdowns found", "count", discards) 283 } 284 for _, tstamp := range uncleanShutdowns { 285 t := time.Unix(int64(tstamp), 0) 286 log.Warn("Unclean shutdown detected", "booted", t, 287 "age", common.PrettyAge(t)) 288 } 289 } 290 return eth, nil 291 } 292 293 func makeExtraData(extra []byte) []byte { 294 if len(extra) == 0 { 295 // create default extradata 296 extra, _ = rlp.EncodeToBytes([]interface{}{ 297 uint(params.VersionMajor<<16 | params.VersionMinor<<8 | params.VersionPatch), 298 "geth", 299 runtime.Version(), 300 runtime.GOOS, 301 }) 302 } 303 if uint64(len(extra)) > params.MaximumExtraDataSize-params.ForkIDSize { 304 log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", params.MaximumExtraDataSize-params.ForkIDSize) 305 extra = nil 306 } 307 return extra 308 } 309 310 // APIs return the collection of RPC services the ethereum package offers. 311 // NOTE, some of these services probably need to be moved to somewhere else. 312 func (s *Ethereum) APIs() []rpc.API { 313 apis := ethapi.GetAPIs(s.APIBackend) 314 315 // Append any APIs exposed explicitly by the consensus engine 316 apis = append(apis, s.engine.APIs(s.BlockChain())...) 317 318 // Append all the local APIs and return 319 return append(apis, []rpc.API{ 320 { 321 Namespace: "eth", 322 Version: "1.0", 323 Service: NewPublicEthereumAPI(s), 324 Public: true, 325 }, { 326 Namespace: "eth", 327 Version: "1.0", 328 Service: NewPublicMinerAPI(s), 329 Public: true, 330 }, { 331 Namespace: "eth", 332 Version: "1.0", 333 Service: downloader.NewPublicDownloaderAPI(s.handler.downloader, s.eventMux), 334 Public: true, 335 }, { 336 Namespace: "miner", 337 Version: "1.0", 338 Service: NewPrivateMinerAPI(s), 339 Public: false, 340 }, { 341 Namespace: "eth", 342 Version: "1.0", 343 Service: filters.NewPublicFilterAPI(s.APIBackend, false, 5*time.Minute, s.config.RangeLimit), 344 Public: true, 345 }, { 346 Namespace: "admin", 347 Version: "1.0", 348 Service: NewPrivateAdminAPI(s), 349 }, { 350 Namespace: "debug", 351 Version: "1.0", 352 Service: NewPublicDebugAPI(s), 353 Public: true, 354 }, { 355 Namespace: "debug", 356 Version: "1.0", 357 Service: NewPrivateDebugAPI(s), 358 }, { 359 Namespace: "net", 360 Version: "1.0", 361 Service: s.netRPCService, 362 Public: true, 363 }, 364 }...) 365 } 366 367 func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) { 368 s.blockchain.ResetWithGenesisBlock(gb) 369 } 370 371 func (s *Ethereum) Etherbase() (eb common.Address, err error) { 372 s.lock.RLock() 373 etherbase := s.etherbase 374 s.lock.RUnlock() 375 376 if etherbase != (common.Address{}) { 377 return etherbase, nil 378 } 379 if wallets := s.AccountManager().Wallets(); len(wallets) > 0 { 380 if accounts := wallets[0].Accounts(); len(accounts) > 0 { 381 etherbase := accounts[0].Address 382 383 s.lock.Lock() 384 s.etherbase = etherbase 385 s.lock.Unlock() 386 387 log.Info("Etherbase automatically configured", "address", etherbase) 388 return etherbase, nil 389 } 390 } 391 return common.Address{}, fmt.Errorf("etherbase must be explicitly specified") 392 } 393 394 // isLocalBlock checks whether the specified block is mined 395 // by local miner accounts. 396 // 397 // We regard two types of accounts as local miner account: etherbase 398 // and accounts specified via `txpool.locals` flag. 399 func (s *Ethereum) isLocalBlock(block *types.Block) bool { 400 author, err := s.engine.Author(block.Header()) 401 if err != nil { 402 log.Warn("Failed to retrieve block author", "number", block.NumberU64(), "hash", block.Hash(), "err", err) 403 return false 404 } 405 // Check whether the given address is etherbase. 406 s.lock.RLock() 407 etherbase := s.etherbase 408 s.lock.RUnlock() 409 if author == etherbase { 410 return true 411 } 412 // Check whether the given address is specified by `txpool.local` 413 // CLI flag. 414 for _, account := range s.config.TxPool.Locals { 415 if account == author { 416 return true 417 } 418 } 419 return false 420 } 421 422 // shouldPreserve checks whether we should preserve the given block 423 // during the chain reorg depending on whether the author of block 424 // is a local account. 425 func (s *Ethereum) shouldPreserve(block *types.Block) bool { 426 // The reason we need to disable the self-reorg preserving for clique 427 // is it can be probable to introduce a deadlock. 428 // 429 // e.g. If there are 7 available signers 430 // 431 // r1 A 432 // r2 B 433 // r3 C 434 // r4 D 435 // r5 A [X] F G 436 // r6 [X] 437 // 438 // In the round5, the inturn signer E is offline, so the worst case 439 // is A, F and G sign the block of round5 and reject the block of opponents 440 // and in the round6, the last available signer B is offline, the whole 441 // network is stuck. 442 if _, ok := s.engine.(*clique.Clique); ok { 443 return false 444 } 445 if _, ok := s.engine.(*parlia.Parlia); ok { 446 return false 447 } 448 return s.isLocalBlock(block) 449 } 450 451 // SetEtherbase sets the mining reward address. 452 func (s *Ethereum) SetEtherbase(etherbase common.Address) { 453 s.lock.Lock() 454 s.etherbase = etherbase 455 s.lock.Unlock() 456 457 s.miner.SetEtherbase(etherbase) 458 } 459 460 // StartMining starts the miner with the given number of CPU threads. If mining 461 // is already running, this method adjust the number of threads allowed to use 462 // and updates the minimum price required by the transaction pool. 463 func (s *Ethereum) StartMining(threads int) error { 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 log.Info("Updated mining threads", "threads", threads) 470 if threads == 0 { 471 threads = -1 // Disable the miner from within 472 } 473 th.SetThreads(threads) 474 } 475 // If the miner was not running, initialize it 476 if !s.IsMining() { 477 // Propagate the initial price point to the transaction pool 478 s.lock.RLock() 479 price := s.gasPrice 480 s.lock.RUnlock() 481 s.txPool.SetGasPrice(price) 482 483 // Configure the local mining address 484 eb, err := s.Etherbase() 485 if err != nil { 486 log.Error("Cannot start mining without etherbase", "err", err) 487 return fmt.Errorf("etherbase missing: %v", err) 488 } 489 if clique, ok := s.engine.(*clique.Clique); ok { 490 wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) 491 if wallet == nil || err != nil { 492 log.Error("Etherbase account unavailable locally", "err", err) 493 return fmt.Errorf("signer missing: %v", err) 494 } 495 clique.Authorize(eb, wallet.SignData) 496 } 497 if parlia, ok := s.engine.(*parlia.Parlia); ok { 498 wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) 499 if wallet == nil || err != nil { 500 log.Error("Etherbase account unavailable locally", "err", err) 501 return fmt.Errorf("signer missing: %v", err) 502 } 503 504 parlia.Authorize(eb, wallet.SignData, wallet.SignTx) 505 } 506 // If mining is started, we can disable the transaction rejection mechanism 507 // introduced to speed sync times. 508 atomic.StoreUint32(&s.handler.acceptTxs, 1) 509 510 go s.miner.Start(eb) 511 } 512 return nil 513 } 514 515 // StopMining terminates the miner, both at the consensus engine level as well as 516 // at the block creation level. 517 func (s *Ethereum) StopMining() { 518 // Update the thread count within the consensus engine 519 type threaded interface { 520 SetThreads(threads int) 521 } 522 if th, ok := s.engine.(threaded); ok { 523 th.SetThreads(-1) 524 } 525 // Stop the block creating itself 526 s.miner.Stop() 527 } 528 529 func (s *Ethereum) IsMining() bool { return s.miner.Mining() } 530 func (s *Ethereum) Miner() *miner.Miner { return s.miner } 531 532 func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } 533 func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } 534 func (s *Ethereum) TxPool() *core.TxPool { return s.txPool } 535 func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } 536 func (s *Ethereum) Engine() consensus.Engine { return s.engine } 537 func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } 538 func (s *Ethereum) IsListening() bool { return true } // Always listening 539 func (s *Ethereum) Downloader() *downloader.Downloader { return s.handler.downloader } 540 func (s *Ethereum) Synced() bool { return atomic.LoadUint32(&s.handler.acceptTxs) == 1 } 541 func (s *Ethereum) ArchiveMode() bool { return s.config.NoPruning } 542 func (s *Ethereum) BloomIndexer() *core.ChainIndexer { return s.bloomIndexer } 543 544 // Protocols returns all the currently configured 545 // network protocols to start. 546 func (s *Ethereum) Protocols() []p2p.Protocol { 547 protos := eth.MakeProtocols((*ethHandler)(s.handler), s.networkID, s.ethDialCandidates) 548 if !s.config.DisableSnapProtocol && s.config.SnapshotCache > 0 { 549 protos = append(protos, snap.MakeProtocols((*snapHandler)(s.handler), s.snapDialCandidates)...) 550 } 551 // diff protocol can still open without snap protocol 552 protos = append(protos, diff.MakeProtocols((*diffHandler)(s.handler), s.snapDialCandidates)...) 553 return protos 554 } 555 556 // Start implements node.Lifecycle, starting all internal goroutines needed by the 557 // Ethereum protocol implementation. 558 func (s *Ethereum) Start() error { 559 eth.StartENRUpdater(s.blockchain, s.p2pServer.LocalNode()) 560 561 // Start the bloom bits servicing goroutines 562 s.startBloomHandlers(params.BloomBitsBlocks) 563 564 // Figure out a max peers count based on the server limits 565 maxPeers := s.p2pServer.MaxPeers 566 if s.config.LightServ > 0 { 567 if s.config.LightPeers >= s.p2pServer.MaxPeers { 568 return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, s.p2pServer.MaxPeers) 569 } 570 maxPeers -= s.config.LightPeers 571 } 572 // Start the networking layer and the light server if requested 573 s.handler.Start(maxPeers) 574 return nil 575 } 576 577 // Stop implements node.Lifecycle, terminating all internal goroutines used by the 578 // Ethereum protocol. 579 func (s *Ethereum) Stop() error { 580 // Stop all the peer-related stuff first. 581 s.ethDialCandidates.Close() 582 s.snapDialCandidates.Close() 583 s.handler.Stop() 584 585 // Then stop everything else. 586 s.bloomIndexer.Close() 587 close(s.closeBloomHandler) 588 s.txPool.Stop() 589 s.miner.Stop() 590 s.miner.Close() 591 // TODO this is a hotfix for https://github.com/phillinzzz/newBsc/issues/22892, need a better solution 592 time.Sleep(5 * time.Second) 593 s.blockchain.Stop() 594 s.engine.Close() 595 rawdb.PopUncleanShutdownMarker(s.chainDb) 596 s.chainDb.Close() 597 s.eventMux.Stop() 598 599 return nil 600 }