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