github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/eth/backend.go (about) 1 package eth 2 3 import ( 4 "errors" 5 "fmt" 6 "github.com/bigzoro/my_simplechain/core/access_contoller" 7 "math/big" 8 "runtime" 9 "sync" 10 "sync/atomic" 11 12 "github.com/bigzoro/my_simplechain/accounts" 13 "github.com/bigzoro/my_simplechain/accounts/abi/bind" 14 "github.com/bigzoro/my_simplechain/common" 15 "github.com/bigzoro/my_simplechain/common/hexutil" 16 "github.com/bigzoro/my_simplechain/consensus" 17 "github.com/bigzoro/my_simplechain/consensus/clique" 18 "github.com/bigzoro/my_simplechain/consensus/ethash" 19 "github.com/bigzoro/my_simplechain/consensus/hotstuff" 20 "github.com/bigzoro/my_simplechain/consensus/pbft" 21 pbftBackend "github.com/bigzoro/my_simplechain/consensus/pbft/backend" 22 "github.com/bigzoro/my_simplechain/consensus/raft" 23 "github.com/bigzoro/my_simplechain/consensus/scrypt" 24 "github.com/bigzoro/my_simplechain/core" 25 "github.com/bigzoro/my_simplechain/core/bloombits" 26 "github.com/bigzoro/my_simplechain/core/rawdb" 27 "github.com/bigzoro/my_simplechain/core/types" 28 "github.com/bigzoro/my_simplechain/core/vm" 29 "github.com/bigzoro/my_simplechain/eth/downloader" 30 "github.com/bigzoro/my_simplechain/eth/filters" 31 "github.com/bigzoro/my_simplechain/eth/gasprice" 32 "github.com/bigzoro/my_simplechain/ethdb" 33 "github.com/bigzoro/my_simplechain/event" 34 "github.com/bigzoro/my_simplechain/internal/ethapi" 35 "github.com/bigzoro/my_simplechain/log" 36 "github.com/bigzoro/my_simplechain/miner" 37 "github.com/bigzoro/my_simplechain/node" 38 "github.com/bigzoro/my_simplechain/p2p" 39 "github.com/bigzoro/my_simplechain/p2p/enr" 40 "github.com/bigzoro/my_simplechain/params" 41 "github.com/bigzoro/my_simplechain/rlp" 42 "github.com/bigzoro/my_simplechain/rpc" 43 ) 44 45 type LesServer interface { 46 Start(p2pServer *p2p.Server) 47 Stop() 48 APIs() []rpc.API 49 Protocols() []p2p.Protocol 50 SetBloomBitsIndexer(bbIndexer *core.ChainIndexer) 51 SetContractBackend(bind.ContractBackend) 52 } 53 54 // SimpleService implements the SimpleService full node service. 55 type SimpleService struct { 56 config *Config 57 chainConfig *params.ChainConfig 58 59 // Channel for shutting down the service 60 shutdownChan chan bool 61 62 // Handlers 63 txPool *core.TxPool 64 blockchain *core.BlockChain 65 handler *handler 66 lesServer LesServer 67 68 // DB interfaces 69 chainDb ethdb.Database // Block chain database 70 71 commonDb ethdb.Database 72 73 eventMux *event.TypeMux 74 engine consensus.Engine 75 accountManager *accounts.Manager 76 77 bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests 78 bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports 79 80 APIBackend *EthAPIBackend 81 82 miner *miner.Miner 83 gasPrice *big.Int 84 85 signer common.Address 86 87 networkID uint64 88 89 netRPCService *ethapi.PublicNetAPI 90 91 lock sync.RWMutex // Protects the variadic fields (e.g. gas price and signer) 92 93 accessControl access_contoller.AccessControlProvider 94 } 95 96 func (s *SimpleService) ChainConfig() *params.ChainConfig { 97 return s.chainConfig 98 } 99 100 func (s *SimpleService) AddLesServer(ls LesServer) { 101 s.lesServer = ls 102 ls.SetBloomBitsIndexer(s.bloomIndexer) 103 } 104 105 // SetContractBackend SetClient sets a rpc client which connecting to our local node. 106 func (s *SimpleService) SetContractBackend(backend bind.ContractBackend) { 107 // Pass the rpc client to les server if it is enabled. 108 if s.lesServer != nil { 109 s.lesServer.SetContractBackend(backend) 110 } 111 } 112 113 // New creates a new SimpleService object (including the 114 // initialisation of the common SimpleService object) 115 func New(ctx *node.ServiceContext, config *Config) (*SimpleService, error) { 116 // Ensure configuration values are compatible and sane 117 if config.SyncMode == downloader.LightSync { 118 return nil, errors.New("can't run eth.SimpleService in light sync mode, use les.LightEthereum") 119 } 120 if !config.SyncMode.IsValid() { 121 return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) 122 } 123 if config.Miner.GasPrice == nil || config.Miner.GasPrice.Cmp(common.Big0) <= 0 { 124 log.Warn("Sanitizing invalid miner gas price", "provided", config.Miner.GasPrice, "updated", DefaultConfig.Miner.GasPrice) 125 config.Miner.GasPrice = new(big.Int).Set(DefaultConfig.Miner.GasPrice) 126 } 127 if config.NoPruning && config.TrieDirtyCache > 0 { 128 config.TrieCleanCache += config.TrieDirtyCache 129 config.TrieDirtyCache = 0 130 } 131 log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024) 132 133 // Assemble the SimpleService object 134 chainDb, err := ctx.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/") 135 if err != nil { 136 return nil, err 137 } 138 commonDb, err := ctx.OpenDatabase("common", config.DatabaseCache, config.DatabaseHandles, "eth/db/common/") 139 if err != nil { 140 return nil, err 141 } 142 chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.OverrideSingularity) 143 if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { 144 return nil, genesisErr 145 } 146 log.Info("Initialised chain configuration", "config", chainConfig) 147 148 eth := &SimpleService{ 149 config: config, 150 chainConfig: chainConfig, 151 chainDb: chainDb, 152 eventMux: ctx.EventMux, 153 accountManager: ctx.AccountManager, 154 engine: CreateConsensusEngine(ctx, chainConfig, config, config.Miner.Notify, config.Miner.Noverify, chainDb), 155 shutdownChan: make(chan bool), 156 networkID: config.NetworkId, 157 gasPrice: config.Miner.GasPrice, 158 signer: config.Miner.Etherbase, 159 bloomRequests: make(chan chan *bloombits.Retrieval), 160 bloomIndexer: NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms), 161 commonDb: commonDb, 162 } 163 164 bcVersion := rawdb.ReadDatabaseVersion(chainDb) 165 var dbVer = "<nil>" 166 if bcVersion != nil { 167 dbVer = fmt.Sprintf("%d", *bcVersion) 168 } 169 log.Info("Initialising SimpleService protocol", "versions", ProtocolVersions, "network", config.NetworkId, "dbversion", dbVer) 170 171 if !config.SkipBcVersionCheck { 172 if bcVersion != nil && *bcVersion > core.BlockChainVersion { 173 return nil, fmt.Errorf("database version is v%d, Geth %s only supports v%d", *bcVersion, params.VersionWithMeta, core.BlockChainVersion) 174 } else if bcVersion == nil || *bcVersion < core.BlockChainVersion { 175 log.Warn("Upgrade blockchain database version", "from", dbVer, "to", core.BlockChainVersion) 176 rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion) 177 } 178 } 179 var ( 180 vmConfig = vm.Config{ 181 EnablePreimageRecording: config.EnablePreimageRecording, 182 EWASMInterpreter: config.EWASMInterpreter, 183 EVMInterpreter: config.EVMInterpreter, 184 } 185 cacheConfig = &core.CacheConfig{ 186 TrieCleanLimit: config.TrieCleanCache, 187 TrieCleanNoPrefetch: config.NoPrefetch, 188 TrieDirtyLimit: config.TrieDirtyCache, 189 TrieDirtyDisabled: config.NoPruning, 190 TrieTimeLimit: config.TrieTimeout, 191 } 192 ) 193 194 eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve) 195 if err != nil { 196 return nil, err 197 } 198 if _, ok := eth.engine.(*hotstuff.Council); ok { 199 config.Hotstuff.ChainReader = eth.blockchain 200 } 201 // Rewind the chain in case of an incompatible config upgrade. 202 if compat, ok := genesisErr.(*params.ConfigCompatError); ok { 203 log.Warn("Rewinding chain to upgrade configuration", "err", compat) 204 eth.blockchain.SetHead(compat.RewindTo) 205 rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) 206 } 207 blockChainCache := core.NewBlockChainCache(eth.blockchain) 208 eth.bloomIndexer.Start(eth.blockchain) 209 210 if config.TxPool.Journal != "" { 211 config.TxPool.Journal = ctx.ResolvePath(config.TxPool.Journal) 212 } 213 eth.txPool = core.NewTxPool(config.TxPool, chainConfig, eth.blockchain) 214 215 // Permit the downloader to use the trie cache allowance during fast sync 216 cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit 217 checkpoint := config.Checkpoint 218 if checkpoint == nil { 219 checkpoint = params.TrustedCheckpoints[genesisHash] 220 } 221 222 var pbs priorBroadcastSelector 223 pbs, _ = eth.engine.(priorBroadcastSelector) 224 if eth.handler, err = NewHandler(chainConfig, checkpoint, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb, cacheLimit, config.Whitelist, pbs); err != nil { 225 return nil, err 226 } 227 eth.handler.SetCommonDb(commonDb) 228 eth.handler.SetNeedCheckPermission(config.NeedCheckPermission) 229 eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine, eth.isLocalBlock, blockChainCache) 230 eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) 231 232 eth.APIBackend = &EthAPIBackend{ctx.ExtRPCEnabled(), eth, nil} 233 gpoParams := config.GPO 234 if gpoParams.Default == nil { 235 gpoParams.Default = config.Miner.GasPrice 236 } 237 eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams) 238 239 //eth.accessControl, err = access_contoller.NewACProvider(eth.chainConfig, "") 240 if err != nil { 241 panic(err) 242 } 243 244 return eth, nil 245 } 246 247 func makeExtraData(extra []byte) []byte { 248 if len(extra) == 0 { 249 // create default extradata 250 extra, _ = rlp.EncodeToBytes([]interface{}{ 251 uint(params.VersionMajor<<16 | params.VersionMinor<<8 | params.VersionPatch), 252 "sipe", 253 runtime.Version(), 254 runtime.GOOS, 255 }) 256 } 257 if uint64(len(extra)) > params.MaximumExtraDataSize { 258 log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", params.MaximumExtraDataSize) 259 extra = nil 260 } 261 return extra 262 } 263 264 // CreateConsensusEngine creates the required type of consensus engine instance for an SimpleService service 265 func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainConfig, config *Config, notify []string, noverify bool, db ethdb.Database) consensus.Engine { 266 // If proof-of-authority is requested, set it up 267 if chainConfig.Clique != nil { 268 return clique.New(chainConfig.Clique, db) 269 } 270 271 // Set up Hotstuff consensus engine 272 if chainConfig.Hotstuff != nil { 273 // snap, _ := hotstuff.LoadHeadSnapshot(db) 274 275 legal := hotstuff.NewLegal(db) 276 // legal.Import(snap) 277 278 if !config.Hotstuff.Mine { 279 return legal 280 } 281 council := hotstuff.NewCouncil(legal, config.Hotstuff.Id, config.Hotstuff.Key) 282 config.Hotstuff.ServiceMaker = council.MakeService 283 return council 284 } 285 286 if chainConfig.Scrypt != nil { 287 // Scrypt and Ethash share the PowMode in this switch cases 288 switch config.Ethash.PowMode { 289 case ethash.ModeFake: 290 log.Warn("Scrypt used in fake mode") 291 return scrypt.NewFaker() 292 case ethash.ModeTest: 293 log.Warn("Scrypt used in test mode") 294 return scrypt.NewTester(notify, noverify) 295 default: 296 engine := scrypt.NewScrypt(scrypt.Config{PowMode: scrypt.ModeNormal}, notify, noverify) 297 engine.SetThreads(-1) // Disable CPU mining 298 return engine 299 } 300 } 301 if chainConfig.Pbft != nil { 302 pbftConfig := &pbft.Config{} 303 if chainConfig.Pbft.Epoch != 0 { 304 pbftConfig.Epoch = chainConfig.Pbft.Epoch 305 } 306 pbftConfig.ProposerPolicy = pbft.ProposerPolicy(chainConfig.Pbft.ProposerPolicy) 307 return pbftBackend.New(&config.Pbft, ctx.NodeKey(), db) 308 } 309 310 if chainConfig.Raft { 311 return raft.New(ctx.NodeKey()) 312 } 313 314 // Otherwise assume proof-of-work 315 switch config.Ethash.PowMode { 316 case ethash.ModeFake: 317 log.Warn("Ethash used in fake mode") 318 return ethash.NewFaker() 319 case ethash.ModeTest: 320 log.Warn("Ethash used in test mode") 321 return ethash.NewTester(nil, noverify) 322 case ethash.ModeShared: 323 log.Warn("Ethash used in shared mode") 324 return ethash.NewShared() 325 default: 326 engine := ethash.New(ethash.Config{ 327 CacheDir: ctx.ResolvePath(config.Ethash.CacheDir), 328 CachesInMem: config.Ethash.CachesInMem, 329 CachesOnDisk: config.Ethash.CachesOnDisk, 330 DatasetDir: config.Ethash.DatasetDir, 331 DatasetsInMem: config.Ethash.DatasetsInMem, 332 DatasetsOnDisk: config.Ethash.DatasetsOnDisk, 333 }, notify, noverify) 334 engine.SetThreads(-1) // Disable CPU mining 335 return engine 336 } 337 } 338 339 // APIs return the collection of RPC services the ethereum package offers. 340 // NOTE, some of these services probably need to be moved to somewhere else. 341 func (s *SimpleService) APIs() []rpc.API { 342 apis := ethapi.GetAPIs(s.APIBackend) 343 344 // Append any APIs exposed explicitly by the les server 345 if s.lesServer != nil { 346 apis = append(apis, s.lesServer.APIs()...) 347 } 348 // Append any APIs exposed explicitly by the consensus engine 349 apis = append(apis, s.engine.APIs(s.BlockChain())...) 350 351 // Append any APIs exposed explicitly by the les server 352 if s.lesServer != nil { 353 apis = append(apis, s.lesServer.APIs()...) 354 } 355 356 // Append all the local APIs and return 357 return append(apis, []rpc.API{ 358 { 359 Namespace: "eth", 360 Version: "1.0", 361 Service: NewPublicEthereumAPI(s), 362 Public: true, 363 }, { 364 Namespace: "eth", 365 Version: "1.0", 366 Service: NewPublicMinerAPI(s), 367 Public: true, 368 }, { 369 Namespace: "eth", 370 Version: "1.0", 371 Service: downloader.NewPublicDownloaderAPI(s.handler.downloader, s.eventMux), 372 Public: true, 373 }, { 374 Namespace: "miner", 375 Version: "1.0", 376 Service: NewPrivateMinerAPI(s), 377 Public: false, 378 }, { 379 Namespace: "eth", 380 Version: "1.0", 381 Service: filters.NewPublicFilterAPI(s.APIBackend, false), 382 Public: true, 383 }, { 384 Namespace: "admin", 385 Version: "1.0", 386 Service: NewPrivateAdminAPI(s), 387 }, { 388 Namespace: "debug", 389 Version: "1.0", 390 Service: NewPublicDebugAPI(s), 391 Public: true, 392 }, { 393 Namespace: "debug", 394 Version: "1.0", 395 Service: NewPrivateDebugAPI(s), 396 }, { 397 Namespace: "net", 398 Version: "1.0", 399 Service: s.netRPCService, 400 Public: true, 401 }, 402 }...) 403 } 404 405 func (s *SimpleService) ResetWithGenesisBlock(gb *types.Block) { 406 s.blockchain.ResetWithGenesisBlock(gb) 407 } 408 409 func (s *SimpleService) GetSigner() (common.Address, error) { 410 s.lock.RLock() 411 signer := s.signer 412 s.lock.RUnlock() 413 //如果是主动设置了,则直接返回 414 if signer != (common.Address{}) { 415 return signer, nil 416 } 417 //如果解锁了一定的账户,则自动取第一个账户设置 418 if wallets := s.AccountManager().Wallets(); len(wallets) > 0 { 419 if loadAccounts := wallets[0].Accounts(); len(loadAccounts) > 0 { 420 signer := loadAccounts[0].Address 421 s.lock.Lock() 422 s.signer = signer 423 s.lock.Unlock() 424 log.Info("GetSigner automatically configured", "address", signer) 425 return signer, nil 426 } 427 } 428 return common.Address{}, fmt.Errorf("signer must be explicitly specified") 429 } 430 431 // isLocalBlock checks whether the specified block is mined 432 // by local miner accounts. 433 // 434 // We regard two types of accounts as local miner account: signer 435 // and accounts specified via `txpool.locals` flag. 436 func (s *SimpleService) isLocalBlock(block *types.Block) bool { 437 author, err := s.engine.Author(block.Header()) 438 if err != nil { 439 log.Warn("Failed to retrieve block author", "number", block.NumberU64(), "hash", block.Hash(), "err", err) 440 return false 441 } 442 // Check whether the given address is signer. 443 s.lock.RLock() 444 signer := s.signer 445 s.lock.RUnlock() 446 if author == signer { 447 return true 448 } 449 // Check whether the given address is specified by `txpool.local` 450 // CLI flag. 451 for _, account := range s.config.TxPool.Locals { 452 if account == author { 453 return true 454 } 455 } 456 return false 457 } 458 459 // shouldPreserve checks whether we should preserve the given block 460 // during the chain reorg depending on whether the author of block 461 // is a local account. 462 func (s *SimpleService) shouldPreserve(block *types.Block) bool { 463 // The reason we need to disable the self-reorg preserving for clique 464 // is it can be probable to introduce a deadlock. 465 // 466 // e.g. If there are 7 available signers 467 // 468 // r1 A 469 // r2 B 470 // r3 C 471 // r4 D 472 // r5 A [X] F G 473 // r6 [X] 474 // 475 // In the round5, the inturn signer E is offline, so the worst case 476 // is A, F and G sign the block of round5 and reject the block of opponents 477 // and in the round6, the last available signer B is offline, the whole 478 // network is stuck. 479 if _, ok := s.engine.(*clique.Clique); ok { 480 return false 481 } 482 return s.isLocalBlock(block) 483 } 484 485 // SetSigner sets the mining reward address. 486 func (s *SimpleService) SetSigner(signer common.Address) { 487 s.lock.Lock() 488 s.signer = signer 489 s.lock.Unlock() 490 491 s.miner.SetEtherbase(signer) 492 } 493 494 // StartMining starts the miner with the given number of CPU threads. If mining 495 // is already running, this method adjust the number of threads allowed to use 496 // and updates the minimum price required by the transaction pool. 497 func (s *SimpleService) StartMining(threads int) error { 498 // Update the thread count within the consensus engine 499 type threaded interface { 500 SetThreads(threads int) 501 } 502 if th, ok := s.engine.(threaded); ok { 503 log.Info("Updated mining threads", "threads", threads) 504 if threads == 0 { 505 threads = -1 // Disable the miner from within 506 } 507 th.SetThreads(threads) 508 } 509 // If the miner was not running, initialize it 510 if !s.IsMining() { 511 // Propagate the initial price point to the transaction pool 512 s.lock.RLock() 513 price := s.gasPrice 514 s.lock.RUnlock() 515 s.txPool.SetGasPrice(price) 516 517 // Configure the local mining address 518 eb, err := s.GetSigner() 519 if err != nil { 520 log.Error("Cannot start mining without signer", "err", err) 521 return fmt.Errorf("signer missing: %v", err) 522 } 523 if cliqueEngine, ok := s.engine.(*clique.Clique); ok { 524 wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) 525 if wallet == nil || err != nil { 526 log.Error("GetSigner account unavailable locally", "err", err) 527 return fmt.Errorf("signer missing: %v", err) 528 } 529 cliqueEngine.Authorize(eb, wallet.SignData) 530 } 531 // If mining is started, we can disable the transaction rejection mechanism 532 // introduced to speed sync times. 533 atomic.StoreUint32(&s.handler.acceptTxs, 1) 534 go s.miner.Start(eb) 535 } 536 return nil 537 } 538 539 // StopMining terminates the miner, both at the consensus engine level as well as 540 // at the block creation level. 541 func (s *SimpleService) StopMining() { 542 // Update the thread count within the consensus engine 543 type threaded interface { 544 SetThreads(threads int) 545 } 546 if th, ok := s.engine.(threaded); ok { 547 th.SetThreads(-1) 548 } 549 // Stop the block creating itself 550 s.miner.Stop() 551 } 552 553 func (s *SimpleService) IsMining() bool { return s.miner.Mining() } 554 func (s *SimpleService) Miner() *miner.Miner { return s.miner } 555 556 func (s *SimpleService) AccountManager() *accounts.Manager { return s.accountManager } 557 func (s *SimpleService) BlockChain() *core.BlockChain { return s.blockchain } 558 func (s *SimpleService) TxPool() *core.TxPool { return s.txPool } 559 func (s *SimpleService) EventMux() *event.TypeMux { return s.eventMux } 560 func (s *SimpleService) Engine() consensus.Engine { return s.engine } 561 func (s *SimpleService) ChainDb() ethdb.Database { return s.chainDb } 562 func (s *SimpleService) IsListening() bool { return true } // Always listening 563 func (s *SimpleService) EthVersion() int { return int(ProtocolVersions[0]) } 564 func (s *SimpleService) NetVersion() uint64 { return s.networkID } 565 func (s *SimpleService) Downloader() *downloader.Downloader { return s.handler.downloader } 566 func (s *SimpleService) Synced() bool { return atomic.LoadUint32(&s.handler.acceptTxs) == 1 } 567 func (s *SimpleService) ArchiveMode() bool { return s.config.NoPruning } 568 func (s *SimpleService) GetEthConfig() *Config { return s.config } 569 func (s *SimpleService) GetSynced() func() bool { return s.Synced } 570 571 // Protocols implements node.Service, returning all the currently configured 572 // network protocols to start. 573 func (s *SimpleService) Protocols() []p2p.Protocol { 574 protocols := make([]p2p.Protocol, len(ProtocolVersions)) 575 for i, vsn := range ProtocolVersions { 576 protocols[i] = s.handler.makeProtocol(vsn) 577 protocols[i].Attributes = []enr.Entry{s.currentEthEntry()} 578 } 579 if s.lesServer != nil { 580 protocols = append(protocols, s.lesServer.Protocols()...) 581 } 582 return protocols 583 } 584 585 // Start implements node.Service, starting all internal goroutines needed by the 586 // SimpleService protocol implementation. 587 func (s *SimpleService) Start(p2pServer *p2p.Server) error { 588 s.startEthEntryUpdate(p2pServer.LocalNode()) 589 590 // Start the bloom bits servicing goroutines 591 s.startBloomHandlers(params.BloomBitsBlocks) 592 593 // Start the RPC service 594 s.netRPCService = ethapi.NewPublicNetAPI(p2pServer, s.NetVersion()) 595 596 // Figure out a max peers count based on the server limits 597 maxPeers := p2pServer.MaxPeers 598 if s.config.LightServ > 0 { 599 if s.config.LightPeers >= p2pServer.MaxPeers { 600 return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, p2pServer.MaxPeers) 601 } 602 maxPeers -= s.config.LightPeers 603 } 604 // Start the networking layer and the light server if requested 605 s.handler.Start(maxPeers) 606 if s.lesServer != nil { 607 s.lesServer.Start(p2pServer) 608 } 609 s.handler.SubscribeCertificateEvent(p2pServer.GetCertificateCh()) 610 return nil 611 } 612 613 // Stop implements node.Service, terminating all internal goroutines used by the 614 // SimpleService protocol. 615 func (s *SimpleService) Stop() error { 616 err := s.bloomIndexer.Close() 617 if err != nil { 618 log.Error("SimpleService bloomIndexer", "err", err) 619 } 620 s.blockchain.Stop() 621 err = s.engine.Close() 622 if err != nil { 623 log.Error("SimpleService engine", "err", err) 624 } 625 s.handler.Stop() 626 if s.lesServer != nil { 627 s.lesServer.Stop() 628 } 629 s.txPool.Stop() 630 s.miner.Stop() 631 s.eventMux.Stop() 632 633 err = s.chainDb.Close() 634 if err != nil { 635 log.Error("SimpleService chainDb", "err", err) 636 } 637 err = s.commonDb.Close() 638 if err != nil { 639 log.Error("SimpleService commonDb", "err", err) 640 } 641 close(s.shutdownChan) 642 return nil 643 } 644 645 func (s *SimpleService) GetSuperManager() *SuperManager { 646 return s.handler.superManager 647 } 648 649 func (s *SimpleService) CommonDb() ethdb.Database { 650 return s.commonDb 651 }