github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/les/txrelay.go (about) 1 // Copyright 2016 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 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/core/types" 24 ) 25 26 type ltrInfo struct { 27 tx *types.Transaction 28 sentTo map[*peer]struct{} 29 } 30 31 type LesTxRelay struct { 32 txSent map[common.Hash]*ltrInfo 33 txPending map[common.Hash]struct{} 34 ps *peerSet 35 peerList []*peer 36 peerStartPos int 37 lock sync.RWMutex 38 39 reqDist *requestDistributor 40 } 41 42 func NewLesTxRelay() *LesTxRelay { 43 return &LesTxRelay{ 44 txSent: make(map[common.Hash]*ltrInfo), 45 txPending: make(map[common.Hash]struct{}), 46 } 47 } 48 49 func (self *LesTxRelay) addPeer(p *peer) { 50 self.lock.Lock() 51 defer self.lock.Unlock() 52 53 self.ps.Register(p) 54 self.peerList = self.ps.AllPeers() 55 } 56 57 func (self *LesTxRelay) removePeer(id string) { 58 self.lock.Lock() 59 defer self.lock.Unlock() 60 61 self.ps.Unregister(id) 62 self.peerList = self.ps.AllPeers() 63 } 64 65 // send sends a list of transactions to at most a given number of peers at 66 // once, never resending any particular transaction to the same peer twice 67 func (self *LesTxRelay) send(txs types.Transactions, count int) { 68 sendTo := make(map[*peer]types.Transactions) 69 70 self.peerStartPos++ // rotate the starting position of the peer list 71 if self.peerStartPos >= len(self.peerList) { 72 self.peerStartPos = 0 73 } 74 75 for _, tx := range txs { 76 hash := tx.Hash() 77 ltr, ok := self.txSent[hash] 78 if !ok { 79 ltr = <rInfo{ 80 tx: tx, 81 sentTo: make(map[*peer]struct{}), 82 } 83 self.txSent[hash] = ltr 84 self.txPending[hash] = struct{}{} 85 } 86 87 if len(self.peerList) > 0 { 88 cnt := count 89 pos := self.peerStartPos 90 for { 91 peer := self.peerList[pos] 92 if _, ok := ltr.sentTo[peer]; !ok { 93 sendTo[peer] = append(sendTo[peer], tx) 94 ltr.sentTo[peer] = struct{}{} 95 cnt-- 96 } 97 if cnt == 0 { 98 break // sent it to the desired number of peers 99 } 100 pos++ 101 if pos == len(self.peerList) { 102 pos = 0 103 } 104 if pos == self.peerStartPos { 105 break // tried all available peers 106 } 107 } 108 } 109 } 110 111 for p, list := range sendTo { 112 pp := p 113 ll := list 114 115 reqID := getNextReqID() 116 rq := &distReq{ 117 getCost: func(dp distPeer) uint64 { 118 peer := dp.(*peer) 119 return peer.GetRequestCost(SendTxMsg, len(ll)) 120 }, 121 canSend: func(dp distPeer) bool { 122 return dp.(*peer) == pp 123 }, 124 request: func(dp distPeer) func() { 125 peer := dp.(*peer) 126 cost := peer.GetRequestCost(SendTxMsg, len(ll)) 127 peer.fcServer.QueueRequest(reqID, cost) 128 return func() { peer.SendTxs(reqID, cost, ll) } 129 }, 130 } 131 self.reqDist.queue(rq) 132 } 133 } 134 135 func (self *LesTxRelay) Send(txs types.Transactions) { 136 self.lock.Lock() 137 defer self.lock.Unlock() 138 139 self.send(txs, 3) 140 } 141 142 func (self *LesTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) { 143 self.lock.Lock() 144 defer self.lock.Unlock() 145 146 for _, hash := range mined { 147 delete(self.txPending, hash) 148 } 149 150 for _, hash := range rollback { 151 self.txPending[hash] = struct{}{} 152 } 153 154 if len(self.txPending) > 0 { 155 txs := make(types.Transactions, len(self.txPending)) 156 i := 0 157 for hash := range self.txPending { 158 txs[i] = self.txSent[hash].tx 159 i++ 160 } 161 self.send(txs, 1) 162 } 163 } 164 165 func (self *LesTxRelay) Discard(hashes []common.Hash) { 166 self.lock.Lock() 167 defer self.lock.Unlock() 168 169 for _, hash := range hashes { 170 delete(self.txSent, hash) 171 delete(self.txPending, hash) 172 } 173 }