github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/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/atheioschain/go-atheios/common" 23 "github.com/atheioschain/go-atheios/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 40 func NewLesTxRelay() *LesTxRelay { 41 return &LesTxRelay{ 42 txSent: make(map[common.Hash]*ltrInfo), 43 txPending: make(map[common.Hash]struct{}), 44 ps: newPeerSet(), 45 } 46 } 47 48 func (self *LesTxRelay) addPeer(p *peer) { 49 self.lock.Lock() 50 defer self.lock.Unlock() 51 52 self.ps.Register(p) 53 self.peerList = self.ps.AllPeers() 54 } 55 56 func (self *LesTxRelay) removePeer(id string) { 57 self.lock.Lock() 58 defer self.lock.Unlock() 59 60 self.ps.Unregister(id) 61 self.peerList = self.ps.AllPeers() 62 } 63 64 // send sends a list of transactions to at most a given number of peers at 65 // once, never resending any particular transaction to the same peer twice 66 func (self *LesTxRelay) send(txs types.Transactions, count int) { 67 sendTo := make(map[*peer]types.Transactions) 68 69 self.peerStartPos++ // rotate the starting position of the peer list 70 if self.peerStartPos >= len(self.peerList) { 71 self.peerStartPos = 0 72 } 73 74 for _, tx := range txs { 75 hash := tx.Hash() 76 ltr, ok := self.txSent[hash] 77 if !ok { 78 ltr = <rInfo{ 79 tx: tx, 80 sentTo: make(map[*peer]struct{}), 81 } 82 self.txSent[hash] = ltr 83 self.txPending[hash] = struct{}{} 84 } 85 86 if len(self.peerList) > 0 { 87 cnt := count 88 pos := self.peerStartPos 89 for { 90 peer := self.peerList[pos] 91 if _, ok := ltr.sentTo[peer]; !ok { 92 sendTo[peer] = append(sendTo[peer], tx) 93 ltr.sentTo[peer] = struct{}{} 94 cnt-- 95 } 96 if cnt == 0 { 97 break // sent it to the desired number of peers 98 } 99 pos++ 100 if pos == len(self.peerList) { 101 pos = 0 102 } 103 if pos == self.peerStartPos { 104 break // tried all available peers 105 } 106 } 107 } 108 } 109 110 for p, list := range sendTo { 111 cost := p.GetRequestCost(SendTxMsg, len(list)) 112 go func(p *peer, list types.Transactions, cost uint64) { 113 p.SendTxs(cost, list) 114 }(p, list, cost) 115 } 116 } 117 118 func (self *LesTxRelay) Send(txs types.Transactions) { 119 self.lock.Lock() 120 defer self.lock.Unlock() 121 122 self.send(txs, 3) 123 } 124 125 func (self *LesTxRelay) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) { 126 self.lock.Lock() 127 defer self.lock.Unlock() 128 129 for _, hash := range mined { 130 delete(self.txPending, hash) 131 } 132 133 for _, hash := range rollback { 134 self.txPending[hash] = struct{}{} 135 } 136 137 if len(self.txPending) > 0 { 138 txs := make(types.Transactions, len(self.txPending)) 139 i := 0 140 for hash := range self.txPending { 141 txs[i] = self.txSent[hash].tx 142 i++ 143 } 144 self.send(txs, 1) 145 } 146 } 147 148 func (self *LesTxRelay) Discard(hashes []common.Hash) { 149 self.lock.Lock() 150 defer self.lock.Unlock() 151 152 for _, hash := range hashes { 153 delete(self.txSent, hash) 154 delete(self.txPending, hash) 155 } 156 }