github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/whisper/whisperv6/peer.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 12:09:52</date>
    10  //</624342690972045312>
    11  
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  //
    25  //
    26  //
    27  
    28  package whisperv6
    29  
    30  import (
    31  	"fmt"
    32  	"math"
    33  	"sync"
    34  	"time"
    35  
    36  	mapset "github.com/deckarep/golang-set"
    37  	"github.com/ethereum/go-ethereum/common"
    38  	"github.com/ethereum/go-ethereum/log"
    39  	"github.com/ethereum/go-ethereum/p2p"
    40  	"github.com/ethereum/go-ethereum/rlp"
    41  )
    42  
    43  //
    44  type Peer struct {
    45  	host *Whisper
    46  	peer *p2p.Peer
    47  	ws   p2p.MsgReadWriter
    48  
    49  	trusted        bool
    50  	powRequirement float64
    51  	bloomMu        sync.Mutex
    52  	bloomFilter    []byte
    53  	fullNode       bool
    54  
    55  known mapset.Set //
    56  
    57  	quit chan struct{}
    58  }
    59  
    60  //
    61  func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
    62  	return &Peer{
    63  		host:           host,
    64  		peer:           remote,
    65  		ws:             rw,
    66  		trusted:        false,
    67  		powRequirement: 0.0,
    68  		known:          mapset.NewSet(),
    69  		quit:           make(chan struct{}),
    70  		bloomFilter:    MakeFullNodeBloom(),
    71  		fullNode:       true,
    72  	}
    73  }
    74  
    75  //
    76  //
    77  func (peer *Peer) start() {
    78  	go peer.update()
    79  	log.Trace("start", "peer", peer.ID())
    80  }
    81  
    82  //
    83  func (peer *Peer) stop() {
    84  	close(peer.quit)
    85  	log.Trace("stop", "peer", peer.ID())
    86  }
    87  
    88  //
    89  //
    90  func (peer *Peer) handshake() error {
    91  //
    92  	errc := make(chan error, 1)
    93  	go func() {
    94  		pow := peer.host.MinPow()
    95  		powConverted := math.Float64bits(pow)
    96  		bloom := peer.host.BloomFilter()
    97  		errc <- p2p.SendItems(peer.ws, statusCode, ProtocolVersion, powConverted, bloom)
    98  	}()
    99  
   100  //
   101  	packet, err := peer.ws.ReadMsg()
   102  	if err != nil {
   103  		return err
   104  	}
   105  	if packet.Code != statusCode {
   106  		return fmt.Errorf("peer [%x] sent packet %x before status packet", peer.ID(), packet.Code)
   107  	}
   108  	s := rlp.NewStream(packet.Payload, uint64(packet.Size))
   109  	_, err = s.List()
   110  	if err != nil {
   111  		return fmt.Errorf("peer [%x] sent bad status message: %v", peer.ID(), err)
   112  	}
   113  	peerVersion, err := s.Uint()
   114  	if err != nil {
   115  		return fmt.Errorf("peer [%x] sent bad status message (unable to decode version): %v", peer.ID(), err)
   116  	}
   117  	if peerVersion != ProtocolVersion {
   118  		return fmt.Errorf("peer [%x]: protocol version mismatch %d != %d", peer.ID(), peerVersion, ProtocolVersion)
   119  	}
   120  
   121  //
   122  	powRaw, err := s.Uint()
   123  	if err == nil {
   124  		pow := math.Float64frombits(powRaw)
   125  		if math.IsInf(pow, 0) || math.IsNaN(pow) || pow < 0.0 {
   126  			return fmt.Errorf("peer [%x] sent bad status message: invalid pow", peer.ID())
   127  		}
   128  		peer.powRequirement = pow
   129  
   130  		var bloom []byte
   131  		err = s.Decode(&bloom)
   132  		if err == nil {
   133  			sz := len(bloom)
   134  			if sz != BloomFilterSize && sz != 0 {
   135  				return fmt.Errorf("peer [%x] sent bad status message: wrong bloom filter size %d", peer.ID(), sz)
   136  			}
   137  			peer.setBloomFilter(bloom)
   138  		}
   139  	}
   140  
   141  	if err := <-errc; err != nil {
   142  		return fmt.Errorf("peer [%x] failed to send status packet: %v", peer.ID(), err)
   143  	}
   144  	return nil
   145  }
   146  
   147  //
   148  //
   149  func (peer *Peer) update() {
   150  //
   151  	expire := time.NewTicker(expirationCycle)
   152  	transmit := time.NewTicker(transmissionCycle)
   153  
   154  //
   155  	for {
   156  		select {
   157  		case <-expire.C:
   158  			peer.expire()
   159  
   160  		case <-transmit.C:
   161  			if err := peer.broadcast(); err != nil {
   162  				log.Trace("broadcast failed", "reason", err, "peer", peer.ID())
   163  				return
   164  			}
   165  
   166  		case <-peer.quit:
   167  			return
   168  		}
   169  	}
   170  }
   171  
   172  //
   173  func (peer *Peer) mark(envelope *Envelope) {
   174  	peer.known.Add(envelope.Hash())
   175  }
   176  
   177  //
   178  func (peer *Peer) marked(envelope *Envelope) bool {
   179  	return peer.known.Contains(envelope.Hash())
   180  }
   181  
   182  //
   183  //
   184  func (peer *Peer) expire() {
   185  	unmark := make(map[common.Hash]struct{})
   186  	peer.known.Each(func(v interface{}) bool {
   187  		if !peer.host.isEnvelopeCached(v.(common.Hash)) {
   188  			unmark[v.(common.Hash)] = struct{}{}
   189  		}
   190  		return true
   191  	})
   192  //
   193  	for hash := range unmark {
   194  		peer.known.Remove(hash)
   195  	}
   196  }
   197  
   198  //
   199  //
   200  func (peer *Peer) broadcast() error {
   201  	envelopes := peer.host.Envelopes()
   202  	bundle := make([]*Envelope, 0, len(envelopes))
   203  	for _, envelope := range envelopes {
   204  		if !peer.marked(envelope) && envelope.PoW() >= peer.powRequirement && peer.bloomMatch(envelope) {
   205  			bundle = append(bundle, envelope)
   206  		}
   207  	}
   208  
   209  	if len(bundle) > 0 {
   210  //
   211  		if err := p2p.Send(peer.ws, messagesCode, bundle); err != nil {
   212  			return err
   213  		}
   214  
   215  //
   216  		for _, e := range bundle {
   217  			peer.mark(e)
   218  		}
   219  
   220  		log.Trace("broadcast", "num. messages", len(bundle))
   221  	}
   222  	return nil
   223  }
   224  
   225  //
   226  func (peer *Peer) ID() []byte {
   227  	id := peer.peer.ID()
   228  	return id[:]
   229  }
   230  
   231  func (peer *Peer) notifyAboutPowRequirementChange(pow float64) error {
   232  	i := math.Float64bits(pow)
   233  	return p2p.Send(peer.ws, powRequirementCode, i)
   234  }
   235  
   236  func (peer *Peer) notifyAboutBloomFilterChange(bloom []byte) error {
   237  	return p2p.Send(peer.ws, bloomFilterExCode, bloom)
   238  }
   239  
   240  func (peer *Peer) bloomMatch(env *Envelope) bool {
   241  	peer.bloomMu.Lock()
   242  	defer peer.bloomMu.Unlock()
   243  	return peer.fullNode || BloomFilterMatch(peer.bloomFilter, env.Bloom())
   244  }
   245  
   246  func (peer *Peer) setBloomFilter(bloom []byte) {
   247  	peer.bloomMu.Lock()
   248  	defer peer.bloomMu.Unlock()
   249  	peer.bloomFilter = bloom
   250  	peer.fullNode = isFullNode(bloom)
   251  	if peer.fullNode && peer.bloomFilter == nil {
   252  		peer.bloomFilter = MakeFullNodeBloom()
   253  	}
   254  }
   255  
   256  func MakeFullNodeBloom() []byte {
   257  	bloom := make([]byte, BloomFilterSize)
   258  	for i := 0; i < BloomFilterSize; i++ {
   259  		bloom[i] = 0xFF
   260  	}
   261  	return bloom
   262  }
   263