github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/les/server.go (about)

     1  // Copyright 2016 The go-simplechain Authors
     2  // This file is part of the go-simplechain library.
     3  //
     4  // The go-simplechain 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-simplechain 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-simplechain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package les
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"github.com/bigzoro/my_simplechain/consensus"
    22  	"github.com/bigzoro/my_simplechain/ethdb"
    23  	"github.com/bigzoro/my_simplechain/event"
    24  	"time"
    25  
    26  	"github.com/bigzoro/my_simplechain/accounts/abi/bind"
    27  	"github.com/bigzoro/my_simplechain/common/mclock"
    28  	"github.com/bigzoro/my_simplechain/core"
    29  	"github.com/bigzoro/my_simplechain/eth"
    30  	"github.com/bigzoro/my_simplechain/les/flowcontrol"
    31  	"github.com/bigzoro/my_simplechain/light"
    32  	"github.com/bigzoro/my_simplechain/log"
    33  	"github.com/bigzoro/my_simplechain/p2p"
    34  	"github.com/bigzoro/my_simplechain/p2p/discv5"
    35  	"github.com/bigzoro/my_simplechain/p2p/enode"
    36  	"github.com/bigzoro/my_simplechain/p2p/enr"
    37  	"github.com/bigzoro/my_simplechain/params"
    38  	"github.com/bigzoro/my_simplechain/rpc"
    39  )
    40  
    41  type LesServer struct {
    42  	lesCommons
    43  
    44  	archiveMode bool // Flag whether the ethereum node runs in archive mode.
    45  	handler     *serverHandler
    46  	lesTopics   []discv5.Topic
    47  	privateKey  *ecdsa.PrivateKey
    48  
    49  	// Flow control and capacity management
    50  	fcManager    *flowcontrol.ClientManager
    51  	costTracker  *costTracker
    52  	defParams    flowcontrol.ServerParams
    53  	servingQueue *servingQueue
    54  	clientPool   *clientPool
    55  
    56  	minCapacity, maxCapacity, freeCapacity uint64
    57  	threadsIdle                            int // Request serving threads count when system is idle.
    58  	threadsBusy                            int // Request serving threads count when system is busy(block insertion).
    59  }
    60  
    61  // add new for mainchain and subchain
    62  type Simplechain interface {
    63  	BlockChain() *core.BlockChain
    64  	TxPool() *core.TxPool
    65  	EventMux() *event.TypeMux
    66  	Engine() consensus.Engine
    67  	ChainDb() ethdb.Database
    68  	ArchiveMode() bool
    69  	GetSynced() func() bool
    70  }
    71  
    72  func NewLesServer(e Simplechain, config *eth.Config) (*LesServer, error) {
    73  	// Collect les protocol version information supported by local node.
    74  	lesTopics := make([]discv5.Topic, len(AdvertiseProtocolVersions))
    75  	for i, pv := range AdvertiseProtocolVersions {
    76  		lesTopics[i] = lesTopic(e.BlockChain().Genesis().Hash(), pv)
    77  	}
    78  	// Calculate the number of threads used to service the light client
    79  	// requests based on the user-specified value.
    80  	threads := config.LightServ * 4 / 100
    81  	if threads < 4 {
    82  		threads = 4
    83  	}
    84  	srv := &LesServer{
    85  		lesCommons: lesCommons{
    86  			genesis:          e.BlockChain().Genesis().Hash(),
    87  			config:           config,
    88  			chainConfig:      e.BlockChain().Config(),
    89  			iConfig:          light.DefaultServerIndexerConfig,
    90  			chainDb:          e.ChainDb(),
    91  			peers:            newPeerSet(),
    92  			chainReader:      e.BlockChain(),
    93  			chtIndexer:       light.NewChtIndexer(e.ChainDb(), nil, params.CHTFrequency, params.HelperTrieProcessConfirmations),
    94  			bloomTrieIndexer: light.NewBloomTrieIndexer(e.ChainDb(), nil, params.BloomBitsBlocks, params.BloomTrieFrequency),
    95  			closeCh:          make(chan struct{}),
    96  		},
    97  		archiveMode:  e.ArchiveMode(),
    98  		lesTopics:    lesTopics,
    99  		fcManager:    flowcontrol.NewClientManager(nil, &mclock.System{}),
   100  		servingQueue: newServingQueue(int64(time.Millisecond*10), float64(config.LightServ)/100),
   101  		threadsBusy:  config.LightServ/100 + 1,
   102  		threadsIdle:  threads,
   103  	}
   104  	srv.handler = newServerHandler(srv, e.BlockChain(), e.ChainDb(), e.TxPool(), e.GetSynced())
   105  	srv.costTracker, srv.minCapacity = newCostTracker(e.ChainDb(), config)
   106  	srv.freeCapacity = srv.minCapacity
   107  
   108  	// Set up checkpoint oracle.
   109  	oracle := config.CheckpointOracle
   110  	if oracle == nil {
   111  		oracle = params.CheckpointOracles[e.BlockChain().Genesis().Hash()]
   112  	}
   113  	srv.oracle = newCheckpointOracle(oracle, srv.localCheckpoint)
   114  
   115  	// Initialize server capacity management fields.
   116  	srv.defParams = flowcontrol.ServerParams{
   117  		BufLimit:    srv.freeCapacity * bufLimitRatio,
   118  		MinRecharge: srv.freeCapacity,
   119  	}
   120  	// LES flow control tries to more or less guarantee the possibility for the
   121  	// clients to send a certain amount of requests at any time and get a quick
   122  	// response. Most of the clients want this guarantee but don't actually need
   123  	// to send requests most of the time. Our goal is to serve as many clients as
   124  	// possible while the actually used server capacity does not exceed the limits
   125  	totalRecharge := srv.costTracker.totalRecharge()
   126  	srv.maxCapacity = srv.freeCapacity * uint64(srv.config.LightPeers)
   127  	if totalRecharge > srv.maxCapacity {
   128  		srv.maxCapacity = totalRecharge
   129  	}
   130  	srv.fcManager.SetCapacityLimits(srv.freeCapacity, srv.maxCapacity, srv.freeCapacity*2)
   131  	srv.clientPool = newClientPool(srv.chainDb, srv.freeCapacity, mclock.System{}, func(id enode.ID) { go srv.peers.Unregister(peerIdToString(id)) })
   132  	srv.clientPool.setDefaultFactors(priceFactors{0, 1, 1}, priceFactors{0, 1, 1})
   133  
   134  	checkpoint := srv.latestLocalCheckpoint()
   135  	if !checkpoint.Empty() {
   136  		log.Info("Loaded latest checkpoint", "section", checkpoint.SectionIndex, "head", checkpoint.SectionHead,
   137  			"chtroot", checkpoint.CHTRoot, "bloomroot", checkpoint.BloomRoot)
   138  	}
   139  	srv.chtIndexer.Start(e.BlockChain())
   140  	return srv, nil
   141  }
   142  
   143  func (s *LesServer) APIs() []rpc.API {
   144  	return []rpc.API{
   145  		{
   146  			Namespace: "les",
   147  			Version:   "1.0",
   148  			Service:   NewPrivateLightAPI(&s.lesCommons),
   149  			Public:    false,
   150  		},
   151  		{
   152  			Namespace: "les",
   153  			Version:   "1.0",
   154  			Service:   NewPrivateLightServerAPI(s),
   155  			Public:    false,
   156  		},
   157  		{
   158  			Namespace: "debug",
   159  			Version:   "1.0",
   160  			Service:   NewPrivateDebugAPI(s),
   161  			Public:    false,
   162  		},
   163  	}
   164  }
   165  
   166  func (s *LesServer) Protocols() []p2p.Protocol {
   167  	ps := s.makeProtocols(ServerProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} {
   168  		if p := s.peers.Peer(peerIdToString(id)); p != nil {
   169  			return p.Info()
   170  		}
   171  		return nil
   172  	})
   173  	// Add "les" ENR entries.
   174  	for i := range ps {
   175  		ps[i].Attributes = []enr.Entry{&lesEntry{}}
   176  	}
   177  	return ps
   178  }
   179  
   180  // Start starts the LES server
   181  func (s *LesServer) Start(srvr *p2p.Server) {
   182  	s.privateKey = srvr.PrivateKey
   183  	s.handler.start()
   184  
   185  	s.wg.Add(1)
   186  	go s.capacityManagement()
   187  
   188  	if srvr.DiscV5 != nil {
   189  		for _, topic := range s.lesTopics {
   190  			topic := topic
   191  			go func() {
   192  				logger := log.New("topic", topic)
   193  				logger.Info("Starting topic registration")
   194  				defer logger.Info("Terminated topic registration")
   195  
   196  				srvr.DiscV5.RegisterTopic(topic, s.closeCh)
   197  			}()
   198  		}
   199  	}
   200  }
   201  
   202  // Stop stops the LES service
   203  func (s *LesServer) Stop() {
   204  	close(s.closeCh)
   205  
   206  	// Disconnect existing sessions.
   207  	// This also closes the gate for any new registrations on the peer set.
   208  	// sessions which are already established but not added to pm.peers yet
   209  	// will exit when they try to register.
   210  	s.peers.Close()
   211  
   212  	s.fcManager.Stop()
   213  	s.costTracker.stop()
   214  	s.handler.stop()
   215  	s.clientPool.stop() // client pool should be closed after handler.
   216  	s.servingQueue.stop()
   217  
   218  	// Note, bloom trie indexer is closed by parent bloombits indexer.
   219  	s.chtIndexer.Close()
   220  	s.wg.Wait()
   221  	log.Info("Les server stopped")
   222  }
   223  
   224  func (s *LesServer) SetBloomBitsIndexer(bloomIndexer *core.ChainIndexer) {
   225  	bloomIndexer.AddChildIndexer(s.bloomTrieIndexer)
   226  }
   227  
   228  // SetClient sets the rpc client and starts running checkpoint contract if it is not yet watched.
   229  func (s *LesServer) SetContractBackend(backend bind.ContractBackend) {
   230  	if s.oracle == nil {
   231  		return
   232  	}
   233  	s.oracle.start(backend)
   234  }
   235  
   236  // capacityManagement starts an event handler loop that updates the recharge curve of
   237  // the client manager and adjusts the client pool's size according to the total
   238  // capacity updates coming from the client manager
   239  func (s *LesServer) capacityManagement() {
   240  	defer s.wg.Done()
   241  
   242  	processCh := make(chan bool, 100)
   243  	sub := s.handler.blockchain.SubscribeBlockProcessingEvent(processCh)
   244  	defer sub.Unsubscribe()
   245  
   246  	totalRechargeCh := make(chan uint64, 100)
   247  	totalRecharge := s.costTracker.subscribeTotalRecharge(totalRechargeCh)
   248  
   249  	totalCapacityCh := make(chan uint64, 100)
   250  	totalCapacity := s.fcManager.SubscribeTotalCapacity(totalCapacityCh)
   251  	s.clientPool.setLimits(s.config.LightPeers, totalCapacity)
   252  
   253  	var (
   254  		busy         bool
   255  		freePeers    uint64
   256  		blockProcess mclock.AbsTime
   257  	)
   258  	updateRecharge := func() {
   259  		if busy {
   260  			s.servingQueue.setThreads(s.threadsBusy)
   261  			s.fcManager.SetRechargeCurve(flowcontrol.PieceWiseLinear{{0, 0}, {totalRecharge, totalRecharge}})
   262  		} else {
   263  			s.servingQueue.setThreads(s.threadsIdle)
   264  			s.fcManager.SetRechargeCurve(flowcontrol.PieceWiseLinear{{0, 0}, {totalRecharge / 10, totalRecharge}, {totalRecharge, totalRecharge}})
   265  		}
   266  	}
   267  	updateRecharge()
   268  
   269  	for {
   270  		select {
   271  		case busy = <-processCh:
   272  			if busy {
   273  				blockProcess = mclock.Now()
   274  			} else {
   275  				blockProcessingTimer.Update(time.Duration(mclock.Now() - blockProcess))
   276  			}
   277  			updateRecharge()
   278  		case totalRecharge = <-totalRechargeCh:
   279  			totalRechargeGauge.Update(int64(totalRecharge))
   280  			updateRecharge()
   281  		case totalCapacity = <-totalCapacityCh:
   282  			totalCapacityGauge.Update(int64(totalCapacity))
   283  			newFreePeers := totalCapacity / s.freeCapacity
   284  			if newFreePeers < freePeers && newFreePeers < uint64(s.config.LightPeers) {
   285  				log.Warn("Reduced free peer connections", "from", freePeers, "to", newFreePeers)
   286  			}
   287  			freePeers = newFreePeers
   288  			s.clientPool.setLimits(s.config.LightPeers, totalCapacity)
   289  		case <-s.closeCh:
   290  			return
   291  		}
   292  	}
   293  }