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

     1  // Copyright 2020 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 zond
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  	"time"
    23  
    24  	"github.com/theQRL/go-zond/common"
    25  	"github.com/theQRL/go-zond/core"
    26  	"github.com/theQRL/go-zond/core/types"
    27  	"github.com/theQRL/go-zond/p2p/enode"
    28  	"github.com/theQRL/go-zond/zond/protocols/zond"
    29  )
    30  
    31  // ethHandler implements the zond.Backend interface to handle the various network
    32  // packets that are sent as replies or broadcasts.
    33  type ethHandler handler
    34  
    35  func (h *ethHandler) Chain() *core.BlockChain { return h.chain }
    36  func (h *ethHandler) TxPool() zond.TxPool     { return h.txpool }
    37  
    38  // RunPeer is invoked when a peer joins on the `zond` protocol.
    39  func (h *ethHandler) RunPeer(peer *zond.Peer, hand zond.Handler) error {
    40  	return (*handler)(h).runEthPeer(peer, hand)
    41  }
    42  
    43  // PeerInfo retrieves all known `eth` information about a peer.
    44  func (h *ethHandler) PeerInfo(id enode.ID) interface{} {
    45  	if p := h.peers.peer(id.String()); p != nil {
    46  		return p.info()
    47  	}
    48  	return nil
    49  }
    50  
    51  // AcceptTxs retrieves whether transaction processing is enabled on the node
    52  // or if inbound transactions should simply be dropped.
    53  func (h *ethHandler) AcceptTxs() bool {
    54  	return h.acceptTxs.Load()
    55  }
    56  
    57  // Handle is invoked from a peer's message handler when it receives a new remote
    58  // message that the handler couldn't consume and serve itself.
    59  func (h *ethHandler) Handle(peer *zond.Peer, packet zond.Packet) error {
    60  	// Consume any broadcasts and announces, forwarding the rest to the downloader
    61  	switch packet := packet.(type) {
    62  	case *zond.NewBlockHashesPacket:
    63  		hashes, numbers := packet.Unpack()
    64  		return h.handleBlockAnnounces(peer, hashes, numbers)
    65  
    66  	case *zond.NewBlockPacket:
    67  		return h.handleBlockBroadcast(peer, packet.Block, packet.TD)
    68  
    69  	case *zond.NewPooledTransactionHashesPacket66:
    70  		return h.txFetcher.Notify(peer.ID(), *packet)
    71  
    72  	case *zond.NewPooledTransactionHashesPacket68:
    73  		return h.txFetcher.Notify(peer.ID(), packet.Hashes)
    74  
    75  	case *zond.TransactionsPacket:
    76  		return h.txFetcher.Enqueue(peer.ID(), *packet, false)
    77  
    78  	case *zond.PooledTransactionsPacket:
    79  		return h.txFetcher.Enqueue(peer.ID(), *packet, true)
    80  
    81  	default:
    82  		return fmt.Errorf("unexpected eth packet type: %T", packet)
    83  	}
    84  }
    85  
    86  // handleBlockAnnounces is invoked from a peer's message handler when it transmits a
    87  // batch of block announcements for the local node to process.
    88  func (h *ethHandler) handleBlockAnnounces(peer *zond.Peer, hashes []common.Hash, numbers []uint64) error {
    89  	// Drop all incoming block announces from the p2p network if
    90  	// the chain already entered the pos stage and disconnect the
    91  	// remote peer.
    92  	if h.merger.PoSFinalized() {
    93  		// TODO (MariusVanDerWijden) drop non-updated peers after the merge
    94  		return nil
    95  		// return errors.New("unexpected block announces")
    96  	}
    97  	// Schedule all the unknown hashes for retrieval
    98  	var (
    99  		unknownHashes  = make([]common.Hash, 0, len(hashes))
   100  		unknownNumbers = make([]uint64, 0, len(numbers))
   101  	)
   102  	for i := 0; i < len(hashes); i++ {
   103  		if !h.chain.HasBlock(hashes[i], numbers[i]) {
   104  			unknownHashes = append(unknownHashes, hashes[i])
   105  			unknownNumbers = append(unknownNumbers, numbers[i])
   106  		}
   107  	}
   108  	for i := 0; i < len(unknownHashes); i++ {
   109  		h.blockFetcher.Notify(peer.ID(), unknownHashes[i], unknownNumbers[i], time.Now(), peer.RequestOneHeader, peer.RequestBodies)
   110  	}
   111  	return nil
   112  }
   113  
   114  // handleBlockBroadcast is invoked from a peer's message handler when it transmits a
   115  // block broadcast for the local node to process.
   116  func (h *ethHandler) handleBlockBroadcast(peer *zond.Peer, block *types.Block, td *big.Int) error {
   117  	// Drop all incoming block announces from the p2p network if
   118  	// the chain already entered the pos stage and disconnect the
   119  	// remote peer.
   120  	if h.merger.PoSFinalized() {
   121  		// TODO (MariusVanDerWijden) drop non-updated peers after the merge
   122  		return nil
   123  		// return errors.New("unexpected block announces")
   124  	}
   125  	// Schedule the block for import
   126  	h.blockFetcher.Enqueue(peer.ID(), block)
   127  
   128  	// Assuming the block is importable by the peer, but possibly not yet done so,
   129  	// calculate the head hash and TD that the peer truly must have.
   130  	var (
   131  		trueHead = block.ParentHash()
   132  		trueTD   = new(big.Int).Sub(td, block.Difficulty())
   133  	)
   134  	// Update the peer's total difficulty if better than the previous
   135  	if _, td := peer.Head(); trueTD.Cmp(td) > 0 {
   136  		peer.SetHead(trueHead, trueTD)
   137  		h.chainSync.handlePeerEvent()
   138  	}
   139  	return nil
   140  }