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  }