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