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