github.com/theQRL/go-zond@v0.1.1/les/client_handler.go (about)

     1  // Copyright 2019 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 les
    18  
    19  import (
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/theQRL/go-zond/common"
    24  	"github.com/theQRL/go-zond/common/mclock"
    25  	"github.com/theQRL/go-zond/core/forkid"
    26  	"github.com/theQRL/go-zond/core/types"
    27  	"github.com/theQRL/go-zond/light"
    28  	"github.com/theQRL/go-zond/p2p"
    29  )
    30  
    31  // clientHandler is responsible for receiving and processing all incoming server
    32  // responses.
    33  type clientHandler struct {
    34  	forkFilter forkid.Filter
    35  	backend    *LightEthereum
    36  
    37  	closeCh chan struct{}
    38  	wg      sync.WaitGroup // WaitGroup used to track all connected peers.
    39  }
    40  
    41  func newClientHandler(backend *LightEthereum) *clientHandler {
    42  	handler := &clientHandler{
    43  		forkFilter: forkid.NewFilter(backend.blockchain),
    44  		backend:    backend,
    45  		closeCh:    make(chan struct{}),
    46  	}
    47  	return handler
    48  }
    49  
    50  func (h *clientHandler) stop() {
    51  	close(h.closeCh)
    52  	h.wg.Wait()
    53  }
    54  
    55  // runPeer is the p2p protocol run function for the given version.
    56  func (h *clientHandler) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) error {
    57  	peer := newServerPeer(int(version), h.backend.config.NetworkId, false, p, newMeteredMsgWriter(rw, int(version)))
    58  	defer peer.close()
    59  	h.wg.Add(1)
    60  	defer h.wg.Done()
    61  	err := h.handle(peer, false)
    62  	return err
    63  }
    64  
    65  func (h *clientHandler) handle(p *serverPeer, noInitAnnounce bool) error {
    66  	if h.backend.peers.len() >= h.backend.config.LightPeers && !p.Peer.Info().Network.Trusted {
    67  		return p2p.DiscTooManyPeers
    68  	}
    69  	p.Log().Debug("Light Ethereum peer connected", "name", p.Name())
    70  
    71  	// Execute the LES handshake
    72  	forkid := forkid.NewID(h.backend.blockchain.Config(), h.backend.BlockChain().Genesis(), h.backend.blockchain.CurrentHeader().Number.Uint64(), h.backend.blockchain.CurrentHeader().Time)
    73  	if err := p.Handshake(h.backend.blockchain.Genesis().Hash(), forkid, h.forkFilter); err != nil {
    74  		p.Log().Debug("Light Ethereum handshake failed", "err", err)
    75  		return err
    76  	}
    77  	// Register peer with the server pool
    78  	if h.backend.serverPool != nil {
    79  		if nvt, err := h.backend.serverPool.RegisterNode(p.Node()); err == nil {
    80  			p.setValueTracker(nvt)
    81  			p.updateVtParams()
    82  			defer func() {
    83  				p.setValueTracker(nil)
    84  				h.backend.serverPool.UnregisterNode(p.Node())
    85  			}()
    86  		} else {
    87  			return err
    88  		}
    89  	}
    90  	// Register the peer locally
    91  	if err := h.backend.peers.register(p); err != nil {
    92  		p.Log().Error("Light Ethereum peer registration failed", "err", err)
    93  		return err
    94  	}
    95  
    96  	serverConnectionGauge.Update(int64(h.backend.peers.len()))
    97  
    98  	connectedAt := mclock.Now()
    99  	defer func() {
   100  		h.backend.peers.unregister(p.id)
   101  		connectionTimer.Update(time.Duration(mclock.Now() - connectedAt))
   102  		serverConnectionGauge.Update(int64(h.backend.peers.len()))
   103  	}()
   104  
   105  	// Mark the peer starts to be served.
   106  	p.serving.Store(true)
   107  	defer p.serving.Store(false)
   108  
   109  	// Spawn a main loop to handle all incoming messages.
   110  	for {
   111  		if err := h.handleMsg(p); err != nil {
   112  			p.Log().Debug("Light Ethereum message handling failed", "err", err)
   113  			p.fcServer.DumpLogs()
   114  			return err
   115  		}
   116  	}
   117  }
   118  
   119  // handleMsg is invoked whenever an inbound message is received from a remote
   120  // peer. The remote connection is torn down upon returning any error.
   121  func (h *clientHandler) handleMsg(p *serverPeer) error {
   122  	// Read the next message from the remote peer, and ensure it's fully consumed
   123  	msg, err := p.rw.ReadMsg()
   124  	if err != nil {
   125  		return err
   126  	}
   127  	p.Log().Trace("Light Ethereum message arrived", "code", msg.Code, "bytes", msg.Size)
   128  
   129  	if msg.Size > ProtocolMaxMsgSize {
   130  		return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize)
   131  	}
   132  	defer msg.Discard()
   133  
   134  	var deliverMsg *Msg
   135  
   136  	// Handle the message depending on its contents
   137  	switch {
   138  	case msg.Code == AnnounceMsg:
   139  		p.Log().Trace("Received announce message")
   140  		var req announceData
   141  		if err := msg.Decode(&req); err != nil {
   142  			return errResp(ErrDecode, "%v: %v", msg, err)
   143  		}
   144  		if err := req.sanityCheck(); err != nil {
   145  			return err
   146  		}
   147  		update, size := req.Update.decode()
   148  		if p.rejectUpdate(size) {
   149  			return errResp(ErrRequestRejected, "")
   150  		}
   151  		p.updateFlowControl(update)
   152  		p.updateVtParams()
   153  
   154  		if req.Hash != (common.Hash{}) {
   155  			if p.announceType == announceTypeNone {
   156  				return errResp(ErrUnexpectedResponse, "")
   157  			}
   158  			if p.announceType == announceTypeSigned {
   159  				if err := req.checkSignature(p.ID(), update); err != nil {
   160  					p.Log().Trace("Invalid announcement signature", "err", err)
   161  					return err
   162  				}
   163  				p.Log().Trace("Valid announcement signature")
   164  			}
   165  			p.Log().Trace("Announce message content", "number", req.Number, "hash", req.Hash, "td", req.Td, "reorg", req.ReorgDepth)
   166  
   167  			// Update peer head information first and then notify the announcement
   168  			p.updateHead(req.Hash, req.Number, req.Td)
   169  		}
   170  	case msg.Code == BlockHeadersMsg:
   171  		p.Log().Trace("Received block header response message")
   172  		var resp struct {
   173  			ReqID, BV uint64
   174  			Headers   []*types.Header
   175  		}
   176  		if err := msg.Decode(&resp); err != nil {
   177  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   178  		}
   179  		p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
   180  		p.answeredRequest(resp.ReqID)
   181  
   182  		deliverMsg = &Msg{
   183  			MsgType: MsgBlockHeaders,
   184  			ReqID:   resp.ReqID,
   185  			Obj:     resp.Headers,
   186  		}
   187  	case msg.Code == BlockBodiesMsg:
   188  		p.Log().Trace("Received block bodies response")
   189  		var resp struct {
   190  			ReqID, BV uint64
   191  			Data      []*types.Body
   192  		}
   193  		if err := msg.Decode(&resp); err != nil {
   194  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   195  		}
   196  		p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
   197  		p.answeredRequest(resp.ReqID)
   198  		deliverMsg = &Msg{
   199  			MsgType: MsgBlockBodies,
   200  			ReqID:   resp.ReqID,
   201  			Obj:     resp.Data,
   202  		}
   203  	case msg.Code == CodeMsg:
   204  		p.Log().Trace("Received code response")
   205  		var resp struct {
   206  			ReqID, BV uint64
   207  			Data      [][]byte
   208  		}
   209  		if err := msg.Decode(&resp); err != nil {
   210  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   211  		}
   212  		p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
   213  		p.answeredRequest(resp.ReqID)
   214  		deliverMsg = &Msg{
   215  			MsgType: MsgCode,
   216  			ReqID:   resp.ReqID,
   217  			Obj:     resp.Data,
   218  		}
   219  	case msg.Code == ReceiptsMsg:
   220  		p.Log().Trace("Received receipts response")
   221  		var resp struct {
   222  			ReqID, BV uint64
   223  			Receipts  []types.Receipts
   224  		}
   225  		if err := msg.Decode(&resp); err != nil {
   226  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   227  		}
   228  		p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
   229  		p.answeredRequest(resp.ReqID)
   230  		deliverMsg = &Msg{
   231  			MsgType: MsgReceipts,
   232  			ReqID:   resp.ReqID,
   233  			Obj:     resp.Receipts,
   234  		}
   235  	case msg.Code == ProofsV2Msg:
   236  		p.Log().Trace("Received les/2 proofs response")
   237  		var resp struct {
   238  			ReqID, BV uint64
   239  			Data      light.NodeList
   240  		}
   241  		if err := msg.Decode(&resp); err != nil {
   242  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   243  		}
   244  		p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
   245  		p.answeredRequest(resp.ReqID)
   246  		deliverMsg = &Msg{
   247  			MsgType: MsgProofsV2,
   248  			ReqID:   resp.ReqID,
   249  			Obj:     resp.Data,
   250  		}
   251  	case msg.Code == HelperTrieProofsMsg:
   252  		p.Log().Trace("Received helper trie proof response")
   253  		var resp struct {
   254  			ReqID, BV uint64
   255  			Data      HelperTrieResps
   256  		}
   257  		if err := msg.Decode(&resp); err != nil {
   258  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   259  		}
   260  		p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
   261  		p.answeredRequest(resp.ReqID)
   262  		deliverMsg = &Msg{
   263  			MsgType: MsgHelperTrieProofs,
   264  			ReqID:   resp.ReqID,
   265  			Obj:     resp.Data,
   266  		}
   267  	case msg.Code == TxStatusMsg:
   268  		p.Log().Trace("Received tx status response")
   269  		var resp struct {
   270  			ReqID, BV uint64
   271  			Status    []light.TxStatus
   272  		}
   273  		if err := msg.Decode(&resp); err != nil {
   274  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   275  		}
   276  		p.fcServer.ReceivedReply(resp.ReqID, resp.BV)
   277  		p.answeredRequest(resp.ReqID)
   278  		deliverMsg = &Msg{
   279  			MsgType: MsgTxStatus,
   280  			ReqID:   resp.ReqID,
   281  			Obj:     resp.Status,
   282  		}
   283  	case msg.Code == StopMsg && p.version >= lpv3:
   284  		p.freeze()
   285  		h.backend.retriever.frozen(p)
   286  		p.Log().Debug("Service stopped")
   287  	case msg.Code == ResumeMsg && p.version >= lpv3:
   288  		var bv uint64
   289  		if err := msg.Decode(&bv); err != nil {
   290  			return errResp(ErrDecode, "msg %v: %v", msg, err)
   291  		}
   292  		p.fcServer.ResumeFreeze(bv)
   293  		p.unfreeze()
   294  		p.Log().Debug("Service resumed")
   295  	default:
   296  		p.Log().Trace("Received invalid message", "code", msg.Code)
   297  		return errResp(ErrInvalidMsgCode, "%v", msg.Code)
   298  	}
   299  	// Deliver the received response to retriever.
   300  	if deliverMsg != nil {
   301  		if err := h.backend.retriever.deliver(p, deliverMsg); err != nil {
   302  			if val := p.errCount.Add(1, mclock.Now()); val > maxResponseErrors {
   303  				return err
   304  			}
   305  		}
   306  	}
   307  	return nil
   308  }