github.com/jimmyx0x/go-ethereum@v1.10.28/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.NewPooledTransactionHashesPacket66: 71 return h.txFetcher.Notify(peer.ID(), *packet) 72 73 case *eth.NewPooledTransactionHashesPacket68: 74 return h.txFetcher.Notify(peer.ID(), packet.Hashes) 75 76 case *eth.TransactionsPacket: 77 return h.txFetcher.Enqueue(peer.ID(), *packet, false) 78 79 case *eth.PooledTransactionsPacket: 80 return h.txFetcher.Enqueue(peer.ID(), *packet, true) 81 82 default: 83 return fmt.Errorf("unexpected eth packet type: %T", packet) 84 } 85 } 86 87 // handleBlockAnnounces is invoked from a peer's message handler when it transmits a 88 // batch of block announcements for the local node to process. 89 func (h *ethHandler) handleBlockAnnounces(peer *eth.Peer, hashes []common.Hash, numbers []uint64) error { 90 // Drop all incoming block announces from the p2p network if 91 // the chain already entered the pos stage and disconnect the 92 // remote peer. 93 if h.merger.PoSFinalized() { 94 // TODO (MariusVanDerWijden) drop non-updated peers after the merge 95 return nil 96 // return errors.New("unexpected block announces") 97 } 98 // Schedule all the unknown hashes for retrieval 99 var ( 100 unknownHashes = make([]common.Hash, 0, len(hashes)) 101 unknownNumbers = make([]uint64, 0, len(numbers)) 102 ) 103 for i := 0; i < len(hashes); i++ { 104 if !h.chain.HasBlock(hashes[i], numbers[i]) { 105 unknownHashes = append(unknownHashes, hashes[i]) 106 unknownNumbers = append(unknownNumbers, numbers[i]) 107 } 108 } 109 for i := 0; i < len(unknownHashes); i++ { 110 h.blockFetcher.Notify(peer.ID(), unknownHashes[i], unknownNumbers[i], time.Now(), peer.RequestOneHeader, peer.RequestBodies) 111 } 112 return nil 113 } 114 115 // handleBlockBroadcast is invoked from a peer's message handler when it transmits a 116 // block broadcast for the local node to process. 117 func (h *ethHandler) handleBlockBroadcast(peer *eth.Peer, block *types.Block, td *big.Int) error { 118 // Drop all incoming block announces from the p2p network if 119 // the chain already entered the pos stage and disconnect the 120 // remote peer. 121 if h.merger.PoSFinalized() { 122 // TODO (MariusVanDerWijden) drop non-updated peers after the merge 123 return nil 124 // return errors.New("unexpected block announces") 125 } 126 // Schedule the block for import 127 h.blockFetcher.Enqueue(peer.ID(), block) 128 129 // Assuming the block is importable by the peer, but possibly not yet done so, 130 // calculate the head hash and TD that the peer truly must have. 131 var ( 132 trueHead = block.ParentHash() 133 trueTD = new(big.Int).Sub(td, block.Difficulty()) 134 ) 135 // Update the peer's total difficulty if better than the previous 136 if _, td := peer.Head(); trueTD.Cmp(td) > 0 { 137 peer.SetHead(trueHead, trueTD) 138 h.chainSync.handlePeerEvent(peer) 139 } 140 return nil 141 }