github.com/alexdevranger/node-1.8.27@v0.0.0-20221128213301-aa5841e41d2d/swarm/pss/pss.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-dubxcoin library. 3 // 4 // The go-dubxcoin 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-dubxcoin 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-dubxcoin library. If not, see <http://www.gnu.org/licenses/>. 16 17 package pss 18 19 import ( 20 "bytes" 21 "context" 22 "crypto/ecdsa" 23 "crypto/rand" 24 "errors" 25 "fmt" 26 "hash" 27 "sync" 28 "time" 29 30 "github.com/alexdevranger/node-1.8.27/common" 31 "github.com/alexdevranger/node-1.8.27/crypto" 32 "github.com/alexdevranger/node-1.8.27/metrics" 33 "github.com/alexdevranger/node-1.8.27/p2p" 34 "github.com/alexdevranger/node-1.8.27/p2p/enode" 35 "github.com/alexdevranger/node-1.8.27/p2p/protocols" 36 "github.com/alexdevranger/node-1.8.27/rpc" 37 "github.com/alexdevranger/node-1.8.27/swarm/log" 38 "github.com/alexdevranger/node-1.8.27/swarm/network" 39 "github.com/alexdevranger/node-1.8.27/swarm/pot" 40 "github.com/alexdevranger/node-1.8.27/swarm/storage" 41 whisper "github.com/alexdevranger/node-1.8.27/whisper/whisperv6" 42 "golang.org/x/crypto/sha3" 43 ) 44 45 const ( 46 defaultPaddingByteSize = 16 47 DefaultMsgTTL = time.Second * 120 48 defaultDigestCacheTTL = time.Second * 10 49 defaultSymKeyCacheCapacity = 512 50 digestLength = 32 // byte length of digest used for pss cache (currently same as swarm chunk hash) 51 defaultWhisperWorkTime = 3 52 defaultWhisperPoW = 0.0000000001 53 defaultMaxMsgSize = 1024 * 1024 54 defaultCleanInterval = time.Second * 60 * 10 55 defaultOutboxCapacity = 100000 56 pssProtocolName = "pss" 57 pssVersion = 2 58 hasherCount = 8 59 ) 60 61 var ( 62 addressLength = len(pot.Address{}) 63 ) 64 65 // cache is used for preventing backwards routing 66 // will also be instrumental in flood guard mechanism 67 // and mailbox implementation 68 type pssCacheEntry struct { 69 expiresAt time.Time 70 } 71 72 // abstraction to enable access to p2p.protocols.Peer.Send 73 type senderPeer interface { 74 Info() *p2p.PeerInfo 75 ID() enode.ID 76 Address() []byte 77 Send(context.Context, interface{}) error 78 } 79 80 // per-key peer related information 81 // member `protected` prevents garbage collection of the instance 82 type pssPeer struct { 83 lastSeen time.Time 84 address PssAddress 85 protected bool 86 } 87 88 // Pss configuration parameters 89 type PssParams struct { 90 MsgTTL time.Duration 91 CacheTTL time.Duration 92 privateKey *ecdsa.PrivateKey 93 SymKeyCacheCapacity int 94 AllowRaw bool // If true, enables sending and receiving messages without builtin pss encryption 95 } 96 97 // Sane defaults for Pss 98 func NewPssParams() *PssParams { 99 return &PssParams{ 100 MsgTTL: DefaultMsgTTL, 101 CacheTTL: defaultDigestCacheTTL, 102 SymKeyCacheCapacity: defaultSymKeyCacheCapacity, 103 } 104 } 105 106 func (params *PssParams) WithPrivateKey(privatekey *ecdsa.PrivateKey) *PssParams { 107 params.privateKey = privatekey 108 return params 109 } 110 111 // Toplevel pss object, takes care of message sending, receiving, decryption and encryption, message handler dispatchers and message forwarding. 112 // 113 // Implements node.Service 114 type Pss struct { 115 *network.Kademlia // we can get the Kademlia address from this 116 *KeyStore 117 118 privateKey *ecdsa.PrivateKey // pss can have it's own independent key 119 auxAPIs []rpc.API // builtins (handshake, test) can add APIs 120 121 // sending and forwarding 122 fwdPool map[string]*protocols.Peer // keep track of all peers sitting on the pssmsg routing layer 123 fwdPoolMu sync.RWMutex 124 fwdCache map[pssDigest]pssCacheEntry // checksum of unique fields from pssmsg mapped to expiry, cache to determine whether to drop msg 125 fwdCacheMu sync.RWMutex 126 cacheTTL time.Duration // how long to keep messages in fwdCache (not implemented) 127 msgTTL time.Duration 128 paddingByteSize int 129 capstring string 130 outbox chan *PssMsg 131 132 // message handling 133 handlers map[Topic]map[*handler]bool // topic and version based pss payload handlers. See pss.Handle() 134 handlersMu sync.RWMutex 135 hashPool sync.Pool 136 topicHandlerCaps map[Topic]*handlerCaps // caches capabilities of each topic's handlers (see handlerCap* consts in types.go) 137 138 // process 139 quitC chan struct{} 140 } 141 142 func (p *Pss) String() string { 143 return fmt.Sprintf("pss: addr %x, pubkey %v", p.BaseAddr(), common.ToHex(crypto.FromECDSAPub(&p.privateKey.PublicKey))) 144 } 145 146 // Creates a new Pss instance. 147 // 148 // In addition to params, it takes a swarm network Kademlia 149 // and a FileStore storage for message cache storage. 150 func NewPss(k *network.Kademlia, params *PssParams) (*Pss, error) { 151 if params.privateKey == nil { 152 return nil, errors.New("missing private key for pss") 153 } 154 cap := p2p.Cap{ 155 Name: pssProtocolName, 156 Version: pssVersion, 157 } 158 ps := &Pss{ 159 Kademlia: k, 160 KeyStore: loadKeyStore(), 161 162 privateKey: params.privateKey, 163 quitC: make(chan struct{}), 164 165 fwdPool: make(map[string]*protocols.Peer), 166 fwdCache: make(map[pssDigest]pssCacheEntry), 167 cacheTTL: params.CacheTTL, 168 msgTTL: params.MsgTTL, 169 paddingByteSize: defaultPaddingByteSize, 170 capstring: cap.String(), 171 outbox: make(chan *PssMsg, defaultOutboxCapacity), 172 173 handlers: make(map[Topic]map[*handler]bool), 174 topicHandlerCaps: make(map[Topic]*handlerCaps), 175 176 hashPool: sync.Pool{ 177 New: func() interface{} { 178 return sha3.NewLegacyKeccak256() 179 }, 180 }, 181 } 182 183 for i := 0; i < hasherCount; i++ { 184 hashfunc := storage.MakeHashFunc(storage.DefaultHash)() 185 ps.hashPool.Put(hashfunc) 186 } 187 188 return ps, nil 189 } 190 191 ///////////////////////////////////////////////////////////////////// 192 // SECTION: node.Service interface 193 ///////////////////////////////////////////////////////////////////// 194 195 func (p *Pss) Start(srv *p2p.Server) error { 196 go func() { 197 ticker := time.NewTicker(defaultCleanInterval) 198 cacheTicker := time.NewTicker(p.cacheTTL) 199 defer ticker.Stop() 200 defer cacheTicker.Stop() 201 for { 202 select { 203 case <-cacheTicker.C: 204 p.cleanFwdCache() 205 case <-ticker.C: 206 p.cleanKeys() 207 case <-p.quitC: 208 return 209 } 210 } 211 }() 212 go func() { 213 for { 214 select { 215 case msg := <-p.outbox: 216 err := p.forward(msg) 217 if err != nil { 218 log.Error(err.Error()) 219 metrics.GetOrRegisterCounter("pss.forward.err", nil).Inc(1) 220 } 221 case <-p.quitC: 222 return 223 } 224 } 225 }() 226 log.Info("Started Pss") 227 log.Info("Loaded EC keys", "pubkey", common.ToHex(crypto.FromECDSAPub(p.PublicKey())), "secp256", common.ToHex(crypto.CompressPubkey(p.PublicKey()))) 228 return nil 229 } 230 231 func (p *Pss) Stop() error { 232 log.Info("Pss shutting down") 233 close(p.quitC) 234 return nil 235 } 236 237 var pssSpec = &protocols.Spec{ 238 Name: pssProtocolName, 239 Version: pssVersion, 240 MaxMsgSize: defaultMaxMsgSize, 241 Messages: []interface{}{ 242 PssMsg{}, 243 }, 244 } 245 246 func (p *Pss) Protocols() []p2p.Protocol { 247 return []p2p.Protocol{ 248 { 249 Name: pssSpec.Name, 250 Version: pssSpec.Version, 251 Length: pssSpec.Length(), 252 Run: p.Run, 253 }, 254 } 255 } 256 257 func (p *Pss) Run(peer *p2p.Peer, rw p2p.MsgReadWriter) error { 258 pp := protocols.NewPeer(peer, rw, pssSpec) 259 p.fwdPoolMu.Lock() 260 p.fwdPool[peer.Info().ID] = pp 261 p.fwdPoolMu.Unlock() 262 return pp.Run(p.handlePssMsg) 263 } 264 265 func (p *Pss) APIs() []rpc.API { 266 apis := []rpc.API{ 267 { 268 Namespace: "pss", 269 Version: "1.0", 270 Service: NewAPI(p), 271 Public: true, 272 }, 273 } 274 apis = append(apis, p.auxAPIs...) 275 return apis 276 } 277 278 // add API methods to the pss API 279 // must be run before node is started 280 func (p *Pss) addAPI(api rpc.API) { 281 p.auxAPIs = append(p.auxAPIs, api) 282 } 283 284 // Returns the swarm Kademlia address of the pss node 285 func (p *Pss) BaseAddr() []byte { 286 return p.Kademlia.BaseAddr() 287 } 288 289 // Returns the pss node's public key 290 func (p *Pss) PublicKey() *ecdsa.PublicKey { 291 return &p.privateKey.PublicKey 292 } 293 294 ///////////////////////////////////////////////////////////////////// 295 // SECTION: Message handling 296 ///////////////////////////////////////////////////////////////////// 297 298 // Links a handler function to a Topic 299 // 300 // All incoming messages with an envelope Topic matching the 301 // topic specified will be passed to the given Handler function. 302 // 303 // There may be an arbitrary number of handler functions per topic. 304 // 305 // Returns a deregister function which needs to be called to 306 // deregister the handler, 307 func (p *Pss) Register(topic *Topic, hndlr *handler) func() { 308 p.handlersMu.Lock() 309 defer p.handlersMu.Unlock() 310 handlers := p.handlers[*topic] 311 if handlers == nil { 312 handlers = make(map[*handler]bool) 313 p.handlers[*topic] = handlers 314 log.Debug("registered handler", "caps", hndlr.caps) 315 } 316 if hndlr.caps == nil { 317 hndlr.caps = &handlerCaps{} 318 } 319 handlers[hndlr] = true 320 if _, ok := p.topicHandlerCaps[*topic]; !ok { 321 p.topicHandlerCaps[*topic] = &handlerCaps{} 322 } 323 if hndlr.caps.raw { 324 p.topicHandlerCaps[*topic].raw = true 325 } 326 if hndlr.caps.prox { 327 p.topicHandlerCaps[*topic].prox = true 328 } 329 return func() { p.deregister(topic, hndlr) } 330 } 331 func (p *Pss) deregister(topic *Topic, hndlr *handler) { 332 p.handlersMu.Lock() 333 defer p.handlersMu.Unlock() 334 handlers := p.handlers[*topic] 335 if len(handlers) > 1 { 336 delete(p.handlers, *topic) 337 // topic caps might have changed now that a handler is gone 338 caps := &handlerCaps{} 339 for h := range handlers { 340 if h.caps.raw { 341 caps.raw = true 342 } 343 if h.caps.prox { 344 caps.prox = true 345 } 346 } 347 p.topicHandlerCaps[*topic] = caps 348 return 349 } 350 delete(handlers, hndlr) 351 } 352 353 // get all registered handlers for respective topics 354 func (p *Pss) getHandlers(topic Topic) map[*handler]bool { 355 p.handlersMu.RLock() 356 defer p.handlersMu.RUnlock() 357 return p.handlers[topic] 358 } 359 360 // Filters incoming messages for processing or forwarding. 361 // Check if address partially matches 362 // If yes, it CAN be for us, and we process it 363 // Only passes error to pss protocol handler if payload is not valid pssmsg 364 func (p *Pss) handlePssMsg(ctx context.Context, msg interface{}) error { 365 metrics.GetOrRegisterCounter("pss.handlepssmsg", nil).Inc(1) 366 pssmsg, ok := msg.(*PssMsg) 367 if !ok { 368 return fmt.Errorf("invalid message type. Expected *PssMsg, got %T ", msg) 369 } 370 log.Trace("handler", "self", label(p.Kademlia.BaseAddr()), "topic", label(pssmsg.Payload.Topic[:])) 371 if int64(pssmsg.Expire) < time.Now().Unix() { 372 metrics.GetOrRegisterCounter("pss.expire", nil).Inc(1) 373 log.Warn("pss filtered expired message", "from", common.ToHex(p.Kademlia.BaseAddr()), "to", common.ToHex(pssmsg.To)) 374 return nil 375 } 376 if p.checkFwdCache(pssmsg) { 377 log.Trace("pss relay block-cache match (process)", "from", common.ToHex(p.Kademlia.BaseAddr()), "to", (common.ToHex(pssmsg.To))) 378 return nil 379 } 380 p.addFwdCache(pssmsg) 381 382 psstopic := Topic(pssmsg.Payload.Topic) 383 384 // raw is simplest handler contingency to check, so check that first 385 var isRaw bool 386 if pssmsg.isRaw() { 387 if _, ok := p.topicHandlerCaps[psstopic]; ok { 388 if !p.topicHandlerCaps[psstopic].raw { 389 log.Debug("No handler for raw message", "topic", psstopic) 390 return nil 391 } 392 } 393 isRaw = true 394 } 395 396 // check if we can be recipient: 397 // - no prox handler on message and partial address matches 398 // - prox handler on message and we are in prox regardless of partial address match 399 // store this result so we don't calculate again on every handler 400 var isProx bool 401 if _, ok := p.topicHandlerCaps[psstopic]; ok { 402 isProx = p.topicHandlerCaps[psstopic].prox 403 } 404 isRecipient := p.isSelfPossibleRecipient(pssmsg, isProx) 405 if !isRecipient { 406 log.Trace("pss was for someone else :'( ... forwarding", "pss", common.ToHex(p.BaseAddr()), "prox", isProx) 407 return p.enqueue(pssmsg) 408 } 409 410 log.Trace("pss for us, yay! ... let's process!", "pss", common.ToHex(p.BaseAddr()), "prox", isProx, "raw", isRaw, "topic", label(pssmsg.Payload.Topic[:])) 411 if err := p.process(pssmsg, isRaw, isProx); err != nil { 412 qerr := p.enqueue(pssmsg) 413 if qerr != nil { 414 return fmt.Errorf("process fail: processerr %v, queueerr: %v", err, qerr) 415 } 416 } 417 return nil 418 419 } 420 421 // Entry point to processing a message for which the current node can be the intended recipient. 422 // Attempts symmetric and asymmetric decryption with stored keys. 423 // Dispatches message to all handlers matching the message topic 424 func (p *Pss) process(pssmsg *PssMsg, raw bool, prox bool) error { 425 metrics.GetOrRegisterCounter("pss.process", nil).Inc(1) 426 427 var err error 428 var recvmsg *whisper.ReceivedMessage 429 var payload []byte 430 var from PssAddress 431 var asymmetric bool 432 var keyid string 433 var keyFunc func(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, PssAddress, error) 434 435 envelope := pssmsg.Payload 436 psstopic := Topic(envelope.Topic) 437 438 if raw { 439 payload = pssmsg.Payload.Data 440 } else { 441 if pssmsg.isSym() { 442 keyFunc = p.processSym 443 } else { 444 asymmetric = true 445 keyFunc = p.processAsym 446 } 447 448 recvmsg, keyid, from, err = keyFunc(envelope) 449 if err != nil { 450 return errors.New("Decryption failed") 451 } 452 payload = recvmsg.Payload 453 } 454 455 if len(pssmsg.To) < addressLength { 456 if err := p.enqueue(pssmsg); err != nil { 457 return err 458 } 459 } 460 p.executeHandlers(psstopic, payload, from, raw, prox, asymmetric, keyid) 461 462 return nil 463 464 } 465 466 func (p *Pss) executeHandlers(topic Topic, payload []byte, from PssAddress, raw bool, prox bool, asymmetric bool, keyid string) { 467 handlers := p.getHandlers(topic) 468 peer := p2p.NewPeer(enode.ID{}, fmt.Sprintf("%x", from), []p2p.Cap{}) 469 for h := range handlers { 470 if !h.caps.raw && raw { 471 log.Warn("norawhandler") 472 continue 473 } 474 if !h.caps.prox && prox { 475 log.Warn("noproxhandler") 476 continue 477 } 478 err := (h.f)(payload, peer, asymmetric, keyid) 479 if err != nil { 480 log.Warn("Pss handler failed", "err", err) 481 } 482 } 483 } 484 485 // will return false if using partial address 486 func (p *Pss) isSelfRecipient(msg *PssMsg) bool { 487 return bytes.Equal(msg.To, p.Kademlia.BaseAddr()) 488 } 489 490 // test match of leftmost bytes in given message to node's Kademlia address 491 func (p *Pss) isSelfPossibleRecipient(msg *PssMsg, prox bool) bool { 492 local := p.Kademlia.BaseAddr() 493 494 // if a partial address matches we are possible recipient regardless of prox 495 // if not and prox is not set, we are surely not 496 if bytes.Equal(msg.To, local[:len(msg.To)]) { 497 498 return true 499 } else if !prox { 500 return false 501 } 502 503 depth := p.Kademlia.NeighbourhoodDepth() 504 po, _ := network.Pof(p.Kademlia.BaseAddr(), msg.To, 0) 505 log.Trace("selfpossible", "po", po, "depth", depth) 506 507 return depth <= po 508 } 509 510 ///////////////////////////////////////////////////////////////////// 511 // SECTION: Message sending 512 ///////////////////////////////////////////////////////////////////// 513 514 func (p *Pss) enqueue(msg *PssMsg) error { 515 select { 516 case p.outbox <- msg: 517 return nil 518 default: 519 } 520 521 metrics.GetOrRegisterCounter("pss.enqueue.outbox.full", nil).Inc(1) 522 return errors.New("outbox full") 523 } 524 525 // Send a raw message (any encryption is responsibility of calling client) 526 // 527 // Will fail if raw messages are disallowed 528 func (p *Pss) SendRaw(address PssAddress, topic Topic, msg []byte) error { 529 if err := validateAddress(address); err != nil { 530 return err 531 } 532 pssMsgParams := &msgParams{ 533 raw: true, 534 } 535 payload := &whisper.Envelope{ 536 Data: msg, 537 Topic: whisper.TopicType(topic), 538 } 539 pssMsg := newPssMsg(pssMsgParams) 540 pssMsg.To = address 541 pssMsg.Expire = uint32(time.Now().Add(p.msgTTL).Unix()) 542 pssMsg.Payload = payload 543 p.addFwdCache(pssMsg) 544 err := p.enqueue(pssMsg) 545 if err != nil { 546 return err 547 } 548 549 // if we have a proxhandler on this topic 550 // also deliver message to ourselves 551 if _, ok := p.topicHandlerCaps[topic]; ok { 552 if p.isSelfPossibleRecipient(pssMsg, true) && p.topicHandlerCaps[topic].prox { 553 return p.process(pssMsg, true, true) 554 } 555 } 556 return nil 557 } 558 559 // Send a message using symmetric encryption 560 // 561 // Fails if the key id does not match any of the stored symmetric keys 562 func (p *Pss) SendSym(symkeyid string, topic Topic, msg []byte) error { 563 symkey, err := p.GetSymmetricKey(symkeyid) 564 if err != nil { 565 return fmt.Errorf("missing valid send symkey %s: %v", symkeyid, err) 566 } 567 psp, ok := p.getPeerSym(symkeyid, topic) 568 if !ok { 569 return fmt.Errorf("invalid topic '%s' for symkey '%s'", topic.String(), symkeyid) 570 } 571 return p.send(psp.address, topic, msg, false, symkey) 572 } 573 574 // Send a message using asymmetric encryption 575 // 576 // Fails if the key id does not match any in of the stored public keys 577 func (p *Pss) SendAsym(pubkeyid string, topic Topic, msg []byte) error { 578 if _, err := crypto.UnmarshalPubkey(common.FromHex(pubkeyid)); err != nil { 579 return fmt.Errorf("Cannot unmarshal pubkey: %x", pubkeyid) 580 } 581 psp, ok := p.getPeerPub(pubkeyid, topic) 582 if !ok { 583 return fmt.Errorf("invalid topic '%s' for pubkey '%s'", topic.String(), pubkeyid) 584 } 585 return p.send(psp.address, topic, msg, true, common.FromHex(pubkeyid)) 586 } 587 588 // Send is payload agnostic, and will accept any byte slice as payload 589 // It generates an whisper envelope for the specified recipient and topic, 590 // and wraps the message payload in it. 591 // TODO: Implement proper message padding 592 func (p *Pss) send(to []byte, topic Topic, msg []byte, asymmetric bool, key []byte) error { 593 metrics.GetOrRegisterCounter("pss.send", nil).Inc(1) 594 595 if key == nil || bytes.Equal(key, []byte{}) { 596 return fmt.Errorf("Zero length key passed to pss send") 597 } 598 padding := make([]byte, p.paddingByteSize) 599 c, err := rand.Read(padding) 600 if err != nil { 601 return err 602 } else if c < p.paddingByteSize { 603 return fmt.Errorf("invalid padding length: %d", c) 604 } 605 wparams := &whisper.MessageParams{ 606 TTL: defaultWhisperTTL, 607 Src: p.privateKey, 608 Topic: whisper.TopicType(topic), 609 WorkTime: defaultWhisperWorkTime, 610 PoW: defaultWhisperPoW, 611 Payload: msg, 612 Padding: padding, 613 } 614 if asymmetric { 615 pk, err := crypto.UnmarshalPubkey(key) 616 if err != nil { 617 return fmt.Errorf("Cannot unmarshal pubkey: %x", key) 618 } 619 wparams.Dst = pk 620 } else { 621 wparams.KeySym = key 622 } 623 // set up outgoing message container, which does encryption and envelope wrapping 624 woutmsg, err := whisper.NewSentMessage(wparams) 625 if err != nil { 626 return fmt.Errorf("failed to generate whisper message encapsulation: %v", err) 627 } 628 // performs encryption. 629 // Does NOT perform / performs negligible PoW due to very low difficulty setting 630 // after this the message is ready for sending 631 envelope, err := woutmsg.Wrap(wparams) 632 if err != nil { 633 return fmt.Errorf("failed to perform whisper encryption: %v", err) 634 } 635 log.Trace("pssmsg whisper done", "env", envelope, "wparams payload", common.ToHex(wparams.Payload), "to", common.ToHex(to), "asym", asymmetric, "key", common.ToHex(key)) 636 637 // prepare for devp2p transport 638 pssMsgParams := &msgParams{ 639 sym: !asymmetric, 640 } 641 pssMsg := newPssMsg(pssMsgParams) 642 pssMsg.To = to 643 pssMsg.Expire = uint32(time.Now().Add(p.msgTTL).Unix()) 644 pssMsg.Payload = envelope 645 err = p.enqueue(pssMsg) 646 if err != nil { 647 return err 648 } 649 if _, ok := p.topicHandlerCaps[topic]; ok { 650 if p.isSelfPossibleRecipient(pssMsg, true) && p.topicHandlerCaps[topic].prox { 651 return p.process(pssMsg, true, true) 652 } 653 } 654 return nil 655 } 656 657 // sendFunc is a helper function that tries to send a message and returns true on success. 658 // It is set here for usage in production, and optionally overridden in tests. 659 var sendFunc func(p *Pss, sp *network.Peer, msg *PssMsg) bool = sendMsg 660 661 // tries to send a message, returns true if successful 662 func sendMsg(p *Pss, sp *network.Peer, msg *PssMsg) bool { 663 var isPssEnabled bool 664 info := sp.Info() 665 for _, capability := range info.Caps { 666 if capability == p.capstring { 667 isPssEnabled = true 668 break 669 } 670 } 671 if !isPssEnabled { 672 log.Error("peer doesn't have matching pss capabilities, skipping", "peer", info.Name, "caps", info.Caps) 673 return false 674 } 675 676 // get the protocol peer from the forwarding peer cache 677 p.fwdPoolMu.RLock() 678 pp := p.fwdPool[sp.Info().ID] 679 p.fwdPoolMu.RUnlock() 680 681 err := pp.Send(context.TODO(), msg) 682 if err != nil { 683 metrics.GetOrRegisterCounter("pss.pp.send.error", nil).Inc(1) 684 log.Error(err.Error()) 685 } 686 687 return err == nil 688 } 689 690 // Forwards a pss message to the peer(s) based on recipient address according to the algorithm 691 // described below. The recipient address can be of any length, and the byte slice will be matched 692 // to the MSB slice of the peer address of the equivalent length. 693 // 694 // If the recipient address (or partial address) is within the neighbourhood depth of the forwarding 695 // node, then it will be forwarded to all the nearest neighbours of the forwarding node. In case of 696 // partial address, it should be forwarded to all the peers matching the partial address, if there 697 // are any; otherwise only to one peer, closest to the recipient address. In any case, if the message 698 // forwarding fails, the node should try to forward it to the next best peer, until the message is 699 // successfully forwarded to at least one peer. 700 func (p *Pss) forward(msg *PssMsg) error { 701 metrics.GetOrRegisterCounter("pss.forward", nil).Inc(1) 702 sent := 0 // number of successful sends 703 to := make([]byte, addressLength) 704 copy(to[:len(msg.To)], msg.To) 705 neighbourhoodDepth := p.Kademlia.NeighbourhoodDepth() 706 707 // luminosity is the opposite of darkness. the more bytes are removed from the address, the higher is darkness, 708 // but the luminosity is less. here luminosity equals the number of bits given in the destination address. 709 luminosityRadius := len(msg.To) * 8 710 711 // proximity order function matching up to neighbourhoodDepth bits (po <= neighbourhoodDepth) 712 pof := pot.DefaultPof(neighbourhoodDepth) 713 714 // soft threshold for msg broadcast 715 broadcastThreshold, _ := pof(to, p.BaseAddr(), 0) 716 if broadcastThreshold > luminosityRadius { 717 broadcastThreshold = luminosityRadius 718 } 719 720 var onlySendOnce bool // indicates if the message should only be sent to one peer with closest address 721 722 // if measured from the recipient address as opposed to the base address (see Kademlia.EachConn 723 // call below), then peers that fall in the same proximity bin as recipient address will appear 724 // [at least] one bit closer, but only if these additional bits are given in the recipient address. 725 if broadcastThreshold < luminosityRadius && broadcastThreshold < neighbourhoodDepth { 726 broadcastThreshold++ 727 onlySendOnce = true 728 } 729 730 p.Kademlia.EachConn(to, addressLength*8, func(sp *network.Peer, po int) bool { 731 if po < broadcastThreshold && sent > 0 { 732 return false // stop iterating 733 } 734 if sendFunc(p, sp, msg) { 735 sent++ 736 if onlySendOnce { 737 return false 738 } 739 if po == addressLength*8 { 740 // stop iterating if successfully sent to the exact recipient (perfect match of full address) 741 return false 742 } 743 } 744 return true 745 }) 746 747 // if we failed to send to anyone, re-insert message in the send-queue 748 if sent == 0 { 749 log.Debug("unable to forward to any peers") 750 if err := p.enqueue(msg); err != nil { 751 metrics.GetOrRegisterCounter("pss.forward.enqueue.error", nil).Inc(1) 752 log.Error(err.Error()) 753 return err 754 } 755 } 756 757 // cache the message 758 p.addFwdCache(msg) 759 return nil 760 } 761 762 ///////////////////////////////////////////////////////////////////// 763 // SECTION: Caching 764 ///////////////////////////////////////////////////////////////////// 765 766 // cleanFwdCache is used to periodically remove expired entries from the forward cache 767 func (p *Pss) cleanFwdCache() { 768 metrics.GetOrRegisterCounter("pss.cleanfwdcache", nil).Inc(1) 769 p.fwdCacheMu.Lock() 770 defer p.fwdCacheMu.Unlock() 771 for k, v := range p.fwdCache { 772 if v.expiresAt.Before(time.Now()) { 773 delete(p.fwdCache, k) 774 } 775 } 776 } 777 778 func label(b []byte) string { 779 return fmt.Sprintf("%04x", b[:2]) 780 } 781 782 // add a message to the cache 783 func (p *Pss) addFwdCache(msg *PssMsg) error { 784 metrics.GetOrRegisterCounter("pss.addfwdcache", nil).Inc(1) 785 786 var entry pssCacheEntry 787 var ok bool 788 789 p.fwdCacheMu.Lock() 790 defer p.fwdCacheMu.Unlock() 791 792 digest := p.digest(msg) 793 if entry, ok = p.fwdCache[digest]; !ok { 794 entry = pssCacheEntry{} 795 } 796 entry.expiresAt = time.Now().Add(p.cacheTTL) 797 p.fwdCache[digest] = entry 798 return nil 799 } 800 801 // check if message is in the cache 802 func (p *Pss) checkFwdCache(msg *PssMsg) bool { 803 p.fwdCacheMu.Lock() 804 defer p.fwdCacheMu.Unlock() 805 806 digest := p.digest(msg) 807 entry, ok := p.fwdCache[digest] 808 if ok { 809 if entry.expiresAt.After(time.Now()) { 810 log.Trace("unexpired cache", "digest", fmt.Sprintf("%x", digest)) 811 metrics.GetOrRegisterCounter("pss.checkfwdcache.unexpired", nil).Inc(1) 812 return true 813 } 814 metrics.GetOrRegisterCounter("pss.checkfwdcache.expired", nil).Inc(1) 815 } 816 return false 817 } 818 819 // Digest of message 820 func (p *Pss) digest(msg *PssMsg) pssDigest { 821 return p.digestBytes(msg.serialize()) 822 } 823 824 func (p *Pss) digestBytes(msg []byte) pssDigest { 825 hasher := p.hashPool.Get().(hash.Hash) 826 defer p.hashPool.Put(hasher) 827 hasher.Reset() 828 hasher.Write(msg) 829 digest := pssDigest{} 830 key := hasher.Sum(nil) 831 copy(digest[:], key[:digestLength]) 832 return digest 833 } 834 835 func validateAddress(addr PssAddress) error { 836 if len(addr) > addressLength { 837 return errors.New("address too long") 838 } 839 return nil 840 }