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