github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/les/txrelay.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:39</date> 10 //</624450096301346816> 11 12 13 package les 14 15 import ( 16 "sync" 17 18 "github.com/ethereum/go-ethereum/common" 19 "github.com/ethereum/go-ethereum/core/types" 20 ) 21 22 type ltrInfo struct { 23 tx *types.Transaction 24 sentTo map[*peer]struct{} 25 } 26 27 type LesTxRelay struct { 28 txSent map[common.Hash]*ltrInfo 29 txPending map[common.Hash]struct{} 30 ps *peerSet 31 peerList []*peer 32 peerStartPos int 33 lock sync.RWMutex 34 35 reqDist *requestDistributor 36 } 37 38 func NewLesTxRelay(ps *peerSet, reqDist *requestDistributor) *LesTxRelay { 39 r := &LesTxRelay{ 40 txSent: make(map[common.Hash]*ltrInfo), 41 txPending: make(map[common.Hash]struct{}), 42 ps: ps, 43 reqDist: reqDist, 44 } 45 ps.notify(r) 46 return r 47 } 48 49 func (self *LesTxRelay) registerPeer(p *peer) { 50 self.lock.Lock() 51 defer self.lock.Unlock() 52 53 self.peerList = self.ps.AllPeers() 54 } 55 56 func (self *LesTxRelay) unregisterPeer(p *peer) { 57 self.lock.Lock() 58 defer self.lock.Unlock() 59 60 self.peerList = self.ps.AllPeers() 61 } 62 63 //send最多向给定数量的对等方发送一个事务列表 64 //一次,不要将任何特定事务重新发送到同一个对等机两次 65 func (self *LesTxRelay) send(txs types.Transactions, count int) { 66 sendTo := make(map[*peer]types.Transactions) 67 68 self.peerStartPos++ //旋转对等列表的起始位置 69 if self.peerStartPos >= len(self.peerList) { 70 self.peerStartPos = 0 71 } 72 73 for _, tx := range txs { 74 hash := tx.Hash() 75 ltr, ok := self.txSent[hash] 76 if !ok { 77 ltr = <rInfo{ 78 tx: tx, 79 sentTo: make(map[*peer]struct{}), 80 } 81 self.txSent[hash] = ltr 82 self.txPending[hash] = struct{}{} 83 } 84 85 if len(self.peerList) > 0 { 86 cnt := count 87 pos := self.peerStartPos 88 for { 89 peer := self.peerList[pos] 90 if _, ok := ltr.sentTo[peer]; !ok { 91 sendTo[peer] = append(sendTo[peer], tx) 92 ltr.sentTo[peer] = struct{}{} 93 cnt-- 94 } 95 if cnt == 0 { 96 break //发送到所需的对等数 97 } 98 pos++ 99 if pos == len(self.peerList) { 100 pos = 0 101 } 102 if pos == self.peerStartPos { 103 break //已尝试所有可用的对等机 104 } 105 } 106 } 107 } 108 109 for p, list := range sendTo { 110 pp := p 111 ll := list 112 113 reqID := genReqID() 114 rq := &distReq{ 115 getCost: func(dp distPeer) uint64 { 116 peer := dp.(*peer) 117 return peer.GetRequestCost(SendTxMsg, len(ll)) 118 }, 119 canSend: func(dp distPeer) bool { 120 return dp.(*peer) == pp 121 }, 122 request: func(dp distPeer) func() { 123 peer := dp.(*peer) 124 cost := peer.GetRequestCost(SendTxMsg, len(ll)) 125 peer.fcServer.QueueRequest(reqID, cost) 126 return func() { peer.SendTxs(reqID, cost, ll) } 127 }, 128 } 129 self.reqDist.queue(rq) 130 } 131 } 132 133 func (self *LesTxRelay) Send(txs types.Transactions) { 134 self.lock.Lock() 135 defer self.lock.Unlock() 136 137 self.send(txs, 3) 138 } 139 140 func (self *LesTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) { 141 self.lock.Lock() 142 defer self.lock.Unlock() 143 144 for _, hash := range mined { 145 delete(self.txPending, hash) 146 } 147 148 for _, hash := range rollback { 149 self.txPending[hash] = struct{}{} 150 } 151 152 if len(self.txPending) > 0 { 153 txs := make(types.Transactions, len(self.txPending)) 154 i := 0 155 for hash := range self.txPending { 156 txs[i] = self.txSent[hash].tx 157 i++ 158 } 159 self.send(txs, 1) 160 } 161 } 162 163 func (self *LesTxRelay) Discard(hashes []common.Hash) { 164 self.lock.Lock() 165 defer self.lock.Unlock() 166 167 for _, hash := range hashes { 168 delete(self.txSent, hash) 169 delete(self.txPending, hash) 170 } 171 } 172