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 = &ltrInfo{
    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  }