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