github.com/status-im/status-go@v1.1.0/waku/waku.go (about) 1 // Copyright 2019 The Waku Library Authors. 2 // 3 // The Waku library is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Lesser General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // (at your option) any later version. 7 // 8 // The Waku library is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty off 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Lesser General Public License for more details. 12 // 13 // You should have received a copy of the GNU Lesser General Public License 14 // along with the Waku library. If not, see <http://www.gnu.org/licenses/>. 15 // 16 // This software uses the go-ethereum library, which is licensed 17 // under the GNU Lesser General Public Library, version 3 or any later. 18 19 package waku 20 21 import ( 22 "bytes" 23 "crypto/ecdsa" 24 "crypto/sha256" 25 "errors" 26 "fmt" 27 "runtime" 28 "sync" 29 "time" 30 31 "github.com/libp2p/go-libp2p/core/peer" 32 33 "github.com/ethereum/go-ethereum/common/hexutil" 34 35 "go.uber.org/zap" 36 37 mapset "github.com/deckarep/golang-set" 38 "golang.org/x/crypto/pbkdf2" 39 40 gethcommon "github.com/ethereum/go-ethereum/common" 41 "github.com/ethereum/go-ethereum/crypto" 42 "github.com/ethereum/go-ethereum/event" 43 "github.com/ethereum/go-ethereum/p2p" 44 "github.com/ethereum/go-ethereum/rlp" 45 "github.com/ethereum/go-ethereum/rpc" 46 47 "github.com/status-im/status-go/eth-node/types" 48 "github.com/status-im/status-go/logutils" 49 "github.com/status-im/status-go/waku/common" 50 v0 "github.com/status-im/status-go/waku/v0" 51 v1 "github.com/status-im/status-go/waku/v1" 52 ) 53 54 const messageQueueLimit = 1024 55 56 type Bridge interface { 57 Pipe() (<-chan *common.Envelope, chan<- *common.Envelope) 58 } 59 60 type settings struct { 61 MaxMsgSize uint32 // Maximal message length allowed by the waku node 62 EnableConfirmations bool // Enable sending message confirmations 63 MinPow float64 // Minimal PoW required by the waku node 64 MinPowTolerance float64 // Minimal PoW tolerated by the waku node for a limited time 65 BloomFilter []byte // Bloom filter for topics of interest for this node 66 BloomFilterTolerance []byte // Bloom filter tolerated by the waku node for a limited time 67 TopicInterest map[common.TopicType]bool // Topic interest for this node 68 TopicInterestTolerance map[common.TopicType]bool // Topic interest tolerated by the waku node for a limited time 69 SoftBlacklistedPeerIDs map[string]bool // SoftBlacklistedPeerIDs is a list of peer ids that we want to keep connected but silently drop any envelope from 70 BloomFilterMode bool // Whether we should match against bloom-filter only 71 LightClient bool // Light client mode enabled does not forward messages 72 RestrictLightClientsConn bool // Restrict connection between two light clients 73 SyncAllowance int // Maximum time in seconds allowed to process the waku-related messages 74 FullNode bool // Whether this is to be run in FullNode settings 75 } 76 77 // Waku represents a dark communication interface through the Ethereum 78 // network, using its very own P2P communication layer. 79 type Waku struct { 80 protocols []p2p.Protocol // Peer description and parameters 81 filters *common.Filters // Message filters installed with Subscribe function 82 83 privateKeys map[string]*ecdsa.PrivateKey // Private key storage 84 symKeys map[string][]byte // Symmetric key storage 85 keyMu sync.RWMutex // Mutex associated with key stores 86 87 envelopes map[gethcommon.Hash]*common.Envelope // Pool of envelopes currently tracked by this node 88 expirations map[uint32]mapset.Set // Message expiration pool 89 poolMu sync.RWMutex // Mutex to sync the message and expiration pools 90 91 stats *common.StatsTracker 92 peers map[common.Peer]struct{} // Set of currently active peers 93 peerMu sync.RWMutex // Mutex to sync the active peer set 94 95 msgQueue chan *common.Envelope // Message queue for normal waku messages 96 p2pMsgQueue chan interface{} // Message queue for peer-to-peer messages (not to be forwarded any further) and history delivery confirmations. 97 p2pMsgIDs map[gethcommon.Hash]bool // Map of the currently processing ids 98 p2pMsgIDsMu sync.RWMutex 99 100 quit chan struct{} // Channel used for graceful exit 101 102 settings settings // Holds configuration settings that can be dynamically changed 103 settingsMu sync.RWMutex // Mutex to sync the settings access 104 105 mailServer MailServer 106 107 rateLimiter *common.PeerRateLimiter 108 109 envelopeFeed event.Feed 110 111 timeSource func() time.Time // source of time for waku 112 113 bridge Bridge 114 bridgeWg sync.WaitGroup 115 cancelBridge chan struct{} 116 117 logger *zap.Logger 118 } 119 120 // New creates a Waku client ready to communicate through the Ethereum P2P network. 121 func New(cfg *Config, logger *zap.Logger) *Waku { 122 if logger == nil { 123 logger = logutils.ZapLogger() 124 } 125 126 logger.Debug("starting waku with config", zap.Any("config", cfg)) 127 if cfg == nil { 128 c := DefaultConfig 129 cfg = &c 130 } 131 132 waku := &Waku{ 133 privateKeys: make(map[string]*ecdsa.PrivateKey), 134 symKeys: make(map[string][]byte), 135 envelopes: make(map[gethcommon.Hash]*common.Envelope), 136 expirations: make(map[uint32]mapset.Set), 137 peers: make(map[common.Peer]struct{}), 138 msgQueue: make(chan *common.Envelope, messageQueueLimit), 139 p2pMsgQueue: make(chan interface{}, messageQueueLimit), 140 p2pMsgIDs: make(map[gethcommon.Hash]bool), 141 quit: make(chan struct{}), 142 timeSource: time.Now, 143 logger: logger, 144 } 145 146 waku.settings = settings{ 147 MaxMsgSize: cfg.MaxMessageSize, 148 MinPow: cfg.MinimumAcceptedPoW, 149 MinPowTolerance: cfg.MinimumAcceptedPoW, 150 EnableConfirmations: cfg.EnableConfirmations, 151 LightClient: cfg.LightClient, 152 FullNode: cfg.FullNode, 153 BloomFilterMode: cfg.BloomFilterMode, 154 SoftBlacklistedPeerIDs: make(map[string]bool), 155 RestrictLightClientsConn: cfg.RestrictLightClientsConn, 156 SyncAllowance: common.DefaultSyncAllowance, 157 } 158 159 for _, peerID := range cfg.SoftBlacklistedPeerIDs { 160 waku.settings.SoftBlacklistedPeerIDs[peerID] = true 161 } 162 163 if cfg.FullNode { 164 waku.settings.BloomFilter = common.MakeFullNodeBloom() 165 waku.settings.BloomFilterTolerance = common.MakeFullNodeBloom() 166 } 167 168 waku.filters = common.NewFilters() 169 waku.stats = &common.StatsTracker{} 170 171 // p2p waku sub-protocol handler 172 waku.protocols = []p2p.Protocol{{ 173 Name: v0.Name, 174 Version: uint(v0.Version), 175 Length: v0.NumberOfMessageCodes, 176 Run: waku.handlePeerV0, 177 NodeInfo: func() interface{} { 178 return map[string]interface{}{ 179 "version": v0.VersionStr, 180 "maxMessageSize": waku.MaxMessageSize(), 181 "minimumPoW": waku.MinPow(), 182 } 183 }, 184 }, 185 { 186 Name: v1.Name, 187 Version: uint(v1.Version), 188 Length: v1.NumberOfMessageCodes, 189 Run: waku.handlePeerV1, 190 NodeInfo: func() interface{} { 191 return map[string]interface{}{ 192 "version": v1.VersionStr, 193 "maxMessageSize": waku.MaxMessageSize(), 194 "minimumPoW": waku.MinPow(), 195 } 196 }, 197 }, 198 } 199 200 return waku 201 } 202 203 func (w *Waku) GetStats() types.StatsSummary { 204 return w.stats.GetStats() 205 } 206 207 // MinPow returns the PoW value required by this node. 208 func (w *Waku) MinPow() float64 { 209 w.settingsMu.RLock() 210 defer w.settingsMu.RUnlock() 211 return w.settings.MinPow 212 } 213 214 // SetMinimumPoW sets the minimal PoW required by this node 215 func (w *Waku) SetMinimumPoW(val float64, tolerate bool) error { 216 if val < 0.0 { 217 return fmt.Errorf("invalid PoW: %f", val) 218 } 219 220 w.settingsMu.Lock() 221 w.settings.MinPow = val 222 w.settingsMu.Unlock() 223 224 w.notifyPeersAboutPowRequirementChange(val) 225 226 if tolerate { 227 go func() { 228 // allow some time before all the peers have processed the notification 229 select { 230 case <-w.quit: 231 return 232 case <-time.After(time.Duration(w.settings.SyncAllowance) * time.Second): 233 w.settingsMu.Lock() 234 w.settings.MinPowTolerance = val 235 w.settingsMu.Unlock() 236 } 237 }() 238 } 239 240 return nil 241 } 242 243 // MinPowTolerance returns the value of minimum PoW which is tolerated for a limited 244 // time after PoW was changed. If sufficient time have elapsed or no change of PoW 245 // have ever occurred, the return value will be the same as return value of MinPow(). 246 func (w *Waku) MinPowTolerance() float64 { 247 w.settingsMu.RLock() 248 defer w.settingsMu.RUnlock() 249 return w.settings.MinPowTolerance 250 } 251 252 // BloomFilter returns the aggregated bloom filter for all the topics of interest. 253 // The nodes are required to send only messages that match the advertised bloom filter. 254 // If a message does not match the bloom, it will tantamount to spam, and the peer will 255 // be disconnected. 256 func (w *Waku) BloomFilter() []byte { 257 if w.FullNode() { 258 return common.MakeFullNodeBloom() 259 } 260 261 w.settingsMu.RLock() 262 defer w.settingsMu.RUnlock() 263 return w.settings.BloomFilter 264 } 265 266 // BloomFilterTolerance returns the bloom filter which is tolerated for a limited 267 // time after new bloom was advertised to the peers. If sufficient time have elapsed 268 // or no change of bloom filter have ever occurred, the return value will be the same 269 // as return value of BloomFilter(). 270 func (w *Waku) BloomFilterTolerance() []byte { 271 if w.FullNode() { 272 return common.MakeFullNodeBloom() 273 } 274 275 w.settingsMu.RLock() 276 defer w.settingsMu.RUnlock() 277 return w.settings.BloomFilterTolerance 278 } 279 280 // BloomFilterMode returns whether the node is running in bloom filter mode 281 func (w *Waku) BloomFilterMode() bool { 282 if w.FullNode() { 283 return true 284 } 285 286 w.settingsMu.RLock() 287 defer w.settingsMu.RUnlock() 288 return w.settings.BloomFilterMode 289 } 290 291 // SetBloomFilter sets the new bloom filter 292 func (w *Waku) SetBloomFilter(bloom []byte) error { 293 if len(bloom) != common.BloomFilterSize { 294 return fmt.Errorf("invalid bloom filter size: %d", len(bloom)) 295 } 296 297 b := make([]byte, common.BloomFilterSize) 298 copy(b, bloom) 299 300 w.settingsMu.Lock() 301 w.settings.BloomFilter = b 302 // Setting bloom filter reset topic interest 303 w.settings.TopicInterest = nil 304 w.settingsMu.Unlock() 305 w.notifyPeersAboutBloomFilterChange(b) 306 307 go func() { 308 // allow some time before all the peers have processed the notification 309 select { 310 case <-w.quit: 311 return 312 case <-time.After(time.Duration(w.settings.SyncAllowance) * time.Second): 313 w.settingsMu.Lock() 314 w.settings.BloomFilterTolerance = b 315 w.settingsMu.Unlock() 316 } 317 318 }() 319 320 return nil 321 } 322 323 // TopicInterest returns the all the topics of interest. 324 // The nodes are required to send only messages that match the advertised topics. 325 // If a message does not match the topic-interest, it will tantamount to spam, and the peer will 326 // be disconnected. 327 func (w *Waku) TopicInterest() []common.TopicType { 328 w.settingsMu.RLock() 329 defer w.settingsMu.RUnlock() 330 // Return nil if FullNode as otherwise topic interest will have precedence 331 if w.settings.FullNode || w.settings.TopicInterest == nil { 332 return nil 333 } 334 topicInterest := make([]common.TopicType, len(w.settings.TopicInterest)) 335 336 i := 0 337 for topic := range w.settings.TopicInterest { 338 topicInterest[i] = topic 339 i++ 340 } 341 return topicInterest 342 } 343 344 // updateTopicInterest adds a new topic interest 345 // and informs the peers 346 func (w *Waku) updateTopicInterest(f *common.Filter) error { 347 newTopicInterest := w.TopicInterest() 348 for _, t := range f.Topics { 349 top := common.BytesToTopic(t) 350 newTopicInterest = append(newTopicInterest, top) 351 } 352 353 return w.SetTopicInterest(newTopicInterest) 354 } 355 356 // SetTopicInterest sets the new topicInterest 357 func (w *Waku) SetTopicInterest(topicInterest []common.TopicType) error { 358 var topicInterestMap map[common.TopicType]bool 359 if len(topicInterest) > common.MaxTopicInterest { 360 return fmt.Errorf("invalid topic interest: %d", len(topicInterest)) 361 } 362 363 if topicInterest != nil { 364 topicInterestMap = make(map[common.TopicType]bool, len(topicInterest)) 365 for _, topic := range topicInterest { 366 topicInterestMap[topic] = true 367 } 368 } 369 370 w.settingsMu.Lock() 371 w.settings.TopicInterest = topicInterestMap 372 // Setting topic interest resets bloom filter 373 w.settings.BloomFilter = nil 374 w.settingsMu.Unlock() 375 w.notifyPeersAboutTopicInterestChange(topicInterest) 376 377 go func() { 378 // allow some time before all the peers have processed the notification 379 select { 380 case <-w.quit: 381 return 382 case <-time.After(time.Duration(w.settings.SyncAllowance) * time.Second): 383 w.settingsMu.Lock() 384 w.settings.TopicInterestTolerance = topicInterestMap 385 w.settingsMu.Unlock() 386 } 387 }() 388 389 return nil 390 } 391 392 // MaxMessageSize returns the maximum accepted message size. 393 func (w *Waku) MaxMessageSize() uint32 { 394 w.settingsMu.RLock() 395 defer w.settingsMu.RUnlock() 396 return w.settings.MaxMsgSize 397 } 398 399 // SetMaxMessageSize sets the maximal message size allowed by this node 400 func (w *Waku) SetMaxMessageSize(size uint32) error { 401 if size > common.MaxMessageSize { 402 return fmt.Errorf("message size too large [%d>%d]", size, common.MaxMessageSize) 403 } 404 w.settingsMu.Lock() 405 w.settings.MaxMsgSize = size 406 w.settingsMu.Unlock() 407 return nil 408 } 409 410 // LightClientMode indicates is this node is light client (does not forward any messages) 411 func (w *Waku) LightClientMode() bool { 412 w.settingsMu.RLock() 413 defer w.settingsMu.RUnlock() 414 return w.settings.LightClient 415 } 416 417 // SetLightClientMode makes node light client (does not forward any messages) 418 func (w *Waku) SetLightClientMode(v bool) { 419 w.settingsMu.Lock() 420 w.settings.LightClient = v 421 w.settingsMu.Unlock() 422 } 423 424 // LightClientModeConnectionRestricted indicates that connection to light client in light client mode not allowed 425 func (w *Waku) LightClientModeConnectionRestricted() bool { 426 w.settingsMu.RLock() 427 defer w.settingsMu.RUnlock() 428 return w.settings.RestrictLightClientsConn 429 } 430 431 // PacketRateLimiting returns RateLimits information for packets 432 func (w *Waku) PacketRateLimits() common.RateLimits { 433 if w.rateLimiter == nil { 434 return common.RateLimits{} 435 } 436 return common.RateLimits{ 437 IPLimits: uint64(w.rateLimiter.PacketLimitPerSecIP), 438 PeerIDLimits: uint64(w.rateLimiter.PacketLimitPerSecPeerID), 439 } 440 } 441 442 // BytesRateLimiting returns RateLimits information for bytes 443 func (w *Waku) BytesRateLimits() common.RateLimits { 444 if w.rateLimiter == nil { 445 return common.RateLimits{} 446 } 447 return common.RateLimits{ 448 IPLimits: uint64(w.rateLimiter.BytesLimitPerSecIP), 449 PeerIDLimits: uint64(w.rateLimiter.BytesLimitPerSecPeerID), 450 } 451 } 452 453 // ConfirmationsEnabled returns true if message confirmations are enabled. 454 func (w *Waku) ConfirmationsEnabled() bool { 455 w.settingsMu.RLock() 456 defer w.settingsMu.RUnlock() 457 return w.settings.EnableConfirmations 458 } 459 460 // CurrentTime returns current time. 461 func (w *Waku) CurrentTime() time.Time { 462 return w.timeSource() 463 } 464 465 // SetTimeSource assigns a particular source of time to a waku object. 466 func (w *Waku) SetTimeSource(timesource func() time.Time) { 467 w.timeSource = timesource 468 } 469 470 // APIs returns the RPC descriptors the Waku implementation offers 471 func (w *Waku) APIs() []rpc.API { 472 return []rpc.API{ 473 { 474 Namespace: v0.Name, 475 Version: v0.VersionStr, 476 Service: NewPublicWakuAPI(w), 477 Public: false, 478 }, 479 } 480 } 481 482 // Protocols returns the waku sub-protocols ran by this particular client. 483 func (w *Waku) Protocols() []p2p.Protocol { 484 return w.protocols 485 } 486 487 // RegisterMailServer registers MailServer interface. 488 // MailServer will process all the incoming messages with p2pRequestCode. 489 func (w *Waku) RegisterMailServer(server MailServer) { 490 w.mailServer = server 491 } 492 493 // SetRateLimiter registers a rate limiter. 494 func (w *Waku) RegisterRateLimiter(r *common.PeerRateLimiter) { 495 w.rateLimiter = r 496 } 497 498 // RegisterBridge registers a new Bridge that moves envelopes 499 // between different subprotocols. 500 // It's important that a bridge is registered before the service 501 // is started, otherwise, it won't read and propagate envelopes. 502 func (w *Waku) RegisterBridge(b Bridge) { 503 if w.cancelBridge != nil { 504 close(w.cancelBridge) 505 } 506 w.bridge = b 507 w.cancelBridge = make(chan struct{}) 508 w.bridgeWg.Add(1) 509 go w.readBridgeLoop() 510 } 511 512 func (w *Waku) readBridgeLoop() { 513 defer w.bridgeWg.Done() 514 out, _ := w.bridge.Pipe() 515 for { 516 select { 517 case <-w.cancelBridge: 518 return 519 case env := <-out: 520 _, err := w.addAndBridge(env, false, true) 521 if err != nil { 522 common.BridgeReceivedFailed.Inc() 523 w.logger.Warn( 524 "failed to add a bridged envelope", 525 zap.Binary("ID", env.Hash().Bytes()), 526 zap.Error(err), 527 ) 528 } else { 529 common.BridgeReceivedSucceed.Inc() 530 w.logger.Debug("bridged envelope successfully", zap.Binary("ID", env.Hash().Bytes())) 531 w.envelopeFeed.Send(common.EnvelopeEvent{ 532 Event: common.EventEnvelopeReceived, 533 Topic: env.Topic, 534 Hash: env.Hash(), 535 }) 536 } 537 } 538 } 539 } 540 541 func (w *Waku) SendEnvelopeEvent(event common.EnvelopeEvent) int { 542 return w.envelopeFeed.Send(event) 543 } 544 545 // SubscribeEnvelopeEvents subscribes to envelopes feed. 546 // In order to prevent blocking waku producers events must be amply buffered. 547 func (w *Waku) SubscribeEnvelopeEvents(events chan<- common.EnvelopeEvent) event.Subscription { 548 return w.envelopeFeed.Subscribe(events) 549 } 550 551 func (w *Waku) notifyPeersAboutPowRequirementChange(pow float64) { 552 arr := w.getPeers() 553 for _, p := range arr { 554 err := p.NotifyAboutPowRequirementChange(pow) 555 if err != nil { 556 // allow one retry 557 err = p.NotifyAboutPowRequirementChange(pow) 558 } 559 if err != nil { 560 w.logger.Warn("failed to notify peer about new pow requirement", zap.Binary("peer", p.ID()), zap.Error(err)) 561 } 562 } 563 } 564 565 func (w *Waku) FullNode() bool { 566 w.settingsMu.RLock() 567 // If full node, nothing to do 568 fullNode := w.settings.FullNode 569 w.settingsMu.RUnlock() 570 return fullNode 571 } 572 573 func (w *Waku) notifyPeersAboutBloomFilterChange(bloom []byte) { 574 575 if w.FullNode() { 576 return 577 } 578 arr := w.getPeers() 579 for _, p := range arr { 580 err := p.NotifyAboutBloomFilterChange(bloom) 581 if err != nil { 582 // allow one retry 583 err = p.NotifyAboutBloomFilterChange(bloom) 584 } 585 if err != nil { 586 w.logger.Warn("failed to notify peer about new bloom filter change", zap.Binary("peer", p.ID()), zap.Error(err)) 587 } 588 } 589 } 590 591 func (w *Waku) notifyPeersAboutTopicInterestChange(topicInterest []common.TopicType) { 592 if w.FullNode() { 593 return 594 } 595 arr := w.getPeers() 596 for _, p := range arr { 597 err := p.NotifyAboutTopicInterestChange(topicInterest) 598 if err != nil { 599 // allow one retry 600 err = p.NotifyAboutTopicInterestChange(topicInterest) 601 } 602 if err != nil { 603 w.logger.Warn("failed to notify peer about new topic interest", zap.Binary("peer", p.ID()), zap.Error(err)) 604 } 605 } 606 } 607 608 func (w *Waku) getPeers() []common.Peer { 609 w.peerMu.Lock() 610 arr := make([]common.Peer, len(w.peers)) 611 i := 0 612 for p := range w.peers { 613 arr[i] = p 614 i++ 615 } 616 w.peerMu.Unlock() 617 return arr 618 } 619 620 // getPeer retrieves peer by ID 621 func (w *Waku) getPeer(peerID []byte) (common.Peer, error) { 622 w.peerMu.Lock() 623 defer w.peerMu.Unlock() 624 for p := range w.peers { 625 if bytes.Equal(peerID, p.ID()) { 626 return p, nil 627 } 628 } 629 return nil, fmt.Errorf("could not find peer with ID: %x", peerID) 630 } 631 632 // AllowP2PMessagesFromPeer marks specific peer trusted, 633 // which will allow it to send historic (expired) messages. 634 func (w *Waku) AllowP2PMessagesFromPeer(peerID []byte) error { 635 p, err := w.getPeer(peerID) 636 if err != nil { 637 return err 638 } 639 p.SetPeerTrusted(true) 640 return nil 641 } 642 643 func (w *Waku) SendHistoricMessageResponse(peerID []byte, payload []byte) error { 644 peer, err := w.getPeer(peerID) 645 if err != nil { 646 return err 647 } 648 return peer.SendHistoricMessageResponse(payload) 649 } 650 651 // SendP2PMessage sends a peer-to-peer message to a specific peer. 652 // It sends one or more envelopes in a single batch. 653 func (w *Waku) SendP2PMessages(peerID []byte, envelopes ...*common.Envelope) error { 654 p, err := w.getPeer(peerID) 655 if err != nil { 656 return err 657 } 658 return p.SendP2PMessages(envelopes) 659 } 660 661 // SendRawP2PDirect sends a peer-to-peer message to a specific peer. 662 // It sends one or more envelopes in a single batch. 663 func (w *Waku) SendRawP2PDirect(peerID []byte, envelopes ...rlp.RawValue) error { 664 p, err := w.getPeer(peerID) 665 if err != nil { 666 return err 667 } 668 return p.SendRawP2PDirect(envelopes) 669 } 670 671 // NewKeyPair generates a new cryptographic identity for the client, and injects 672 // it into the known identities for message decryption. Returns ID of the new key pair. 673 func (w *Waku) NewKeyPair() (string, error) { 674 key, err := crypto.GenerateKey() 675 if err != nil || !validatePrivateKey(key) { 676 key, err = crypto.GenerateKey() // retry once 677 } 678 if err != nil { 679 return "", err 680 } 681 if !validatePrivateKey(key) { 682 return "", fmt.Errorf("failed to generate valid key") 683 } 684 685 id, err := toDeterministicID(hexutil.Encode(crypto.FromECDSAPub(&key.PublicKey)), common.KeyIDSize) 686 if err != nil { 687 return "", err 688 } 689 690 w.keyMu.Lock() 691 defer w.keyMu.Unlock() 692 693 if w.privateKeys[id] != nil { 694 return "", fmt.Errorf("failed to generate unique ID") 695 } 696 w.privateKeys[id] = key 697 return id, nil 698 } 699 700 // DeleteKeyPair deletes the specified key if it exists. 701 func (w *Waku) DeleteKeyPair(key string) bool { 702 deterministicID, err := toDeterministicID(key, common.KeyIDSize) 703 if err != nil { 704 return false 705 } 706 707 w.keyMu.Lock() 708 defer w.keyMu.Unlock() 709 710 if w.privateKeys[deterministicID] != nil { 711 delete(w.privateKeys, deterministicID) 712 return true 713 } 714 return false 715 } 716 717 // AddKeyPair imports a asymmetric private key and returns it identifier. 718 func (w *Waku) AddKeyPair(key *ecdsa.PrivateKey) (string, error) { 719 id, err := makeDeterministicID(hexutil.Encode(crypto.FromECDSAPub(&key.PublicKey)), common.KeyIDSize) 720 if err != nil { 721 return "", err 722 } 723 if w.HasKeyPair(id) { 724 return id, nil // no need to re-inject 725 } 726 727 w.keyMu.Lock() 728 w.privateKeys[id] = key 729 w.keyMu.Unlock() 730 731 return id, nil 732 } 733 734 // SelectKeyPair adds cryptographic identity, and makes sure 735 // that it is the only private key known to the node. 736 func (w *Waku) SelectKeyPair(key *ecdsa.PrivateKey) error { 737 id, err := makeDeterministicID(hexutil.Encode(crypto.FromECDSAPub(&key.PublicKey)), common.KeyIDSize) 738 if err != nil { 739 return err 740 } 741 742 w.keyMu.Lock() 743 defer w.keyMu.Unlock() 744 745 w.privateKeys = make(map[string]*ecdsa.PrivateKey) // reset key store 746 w.privateKeys[id] = key 747 748 return nil 749 } 750 751 // DeleteKeyPairs removes all cryptographic identities known to the node 752 func (w *Waku) DeleteKeyPairs() error { 753 w.keyMu.Lock() 754 defer w.keyMu.Unlock() 755 756 w.privateKeys = make(map[string]*ecdsa.PrivateKey) 757 758 return nil 759 } 760 761 // HasKeyPair checks if the waku node is configured with the private key 762 // of the specified public pair. 763 func (w *Waku) HasKeyPair(id string) bool { 764 deterministicID, err := toDeterministicID(id, common.KeyIDSize) 765 if err != nil { 766 return false 767 } 768 769 w.keyMu.RLock() 770 defer w.keyMu.RUnlock() 771 return w.privateKeys[deterministicID] != nil 772 } 773 774 // GetPrivateKey retrieves the private key of the specified identity. 775 func (w *Waku) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) { 776 deterministicID, err := toDeterministicID(id, common.KeyIDSize) 777 if err != nil { 778 return nil, err 779 } 780 781 w.keyMu.RLock() 782 defer w.keyMu.RUnlock() 783 key := w.privateKeys[deterministicID] 784 if key == nil { 785 return nil, fmt.Errorf("invalid id") 786 } 787 return key, nil 788 } 789 790 // GenerateSymKey generates a random symmetric key and stores it under id, 791 // which is then returned. Will be used in the future for session key exchange. 792 func (w *Waku) GenerateSymKey() (string, error) { 793 key, err := common.GenerateSecureRandomData(common.AESKeyLength) 794 if err != nil { 795 return "", err 796 } else if !common.ValidateDataIntegrity(key, common.AESKeyLength) { 797 return "", fmt.Errorf("error in GenerateSymKey: crypto/rand failed to generate random data") 798 } 799 800 id, err := common.GenerateRandomID() 801 if err != nil { 802 return "", fmt.Errorf("failed to generate ID: %s", err) 803 } 804 805 w.keyMu.Lock() 806 defer w.keyMu.Unlock() 807 808 if w.symKeys[id] != nil { 809 return "", fmt.Errorf("failed to generate unique ID") 810 } 811 w.symKeys[id] = key 812 return id, nil 813 } 814 815 // AddSymKey stores the key with a given id. 816 func (w *Waku) AddSymKey(id string, key []byte) (string, error) { 817 deterministicID, err := toDeterministicID(id, common.KeyIDSize) 818 if err != nil { 819 return "", err 820 } 821 822 w.keyMu.Lock() 823 defer w.keyMu.Unlock() 824 825 if w.symKeys[deterministicID] != nil { 826 return "", fmt.Errorf("key already exists: %v", id) 827 } 828 w.symKeys[deterministicID] = key 829 return deterministicID, nil 830 } 831 832 // AddSymKeyDirect stores the key, and returns its id. 833 func (w *Waku) AddSymKeyDirect(key []byte) (string, error) { 834 if len(key) != common.AESKeyLength { 835 return "", fmt.Errorf("wrong key size: %d", len(key)) 836 } 837 838 id, err := common.GenerateRandomID() 839 if err != nil { 840 return "", fmt.Errorf("failed to generate ID: %s", err) 841 } 842 843 w.keyMu.Lock() 844 defer w.keyMu.Unlock() 845 846 if w.symKeys[id] != nil { 847 return "", fmt.Errorf("failed to generate unique ID") 848 } 849 w.symKeys[id] = key 850 return id, nil 851 } 852 853 // AddSymKeyFromPassword generates the key from password, stores it, and returns its id. 854 func (w *Waku) AddSymKeyFromPassword(password string) (string, error) { 855 id, err := common.GenerateRandomID() 856 if err != nil { 857 return "", fmt.Errorf("failed to generate ID: %s", err) 858 } 859 if w.HasSymKey(id) { 860 return "", fmt.Errorf("failed to generate unique ID") 861 } 862 863 // kdf should run no less than 0.1 seconds on an average computer, 864 // because it's an once in a session experience 865 derived := pbkdf2.Key([]byte(password), nil, 65356, common.AESKeyLength, sha256.New) 866 867 w.keyMu.Lock() 868 defer w.keyMu.Unlock() 869 870 // double check is necessary, because deriveKeyMaterial() is very slow 871 if w.symKeys[id] != nil { 872 return "", fmt.Errorf("critical error: failed to generate unique ID") 873 } 874 w.symKeys[id] = derived 875 return id, nil 876 } 877 878 // HasSymKey returns true if there is a key associated with the given id. 879 // Otherwise returns false. 880 func (w *Waku) HasSymKey(id string) bool { 881 w.keyMu.RLock() 882 defer w.keyMu.RUnlock() 883 return w.symKeys[id] != nil 884 } 885 886 // DeleteSymKey deletes the key associated with the name string if it exists. 887 func (w *Waku) DeleteSymKey(id string) bool { 888 w.keyMu.Lock() 889 defer w.keyMu.Unlock() 890 if w.symKeys[id] != nil { 891 delete(w.symKeys, id) 892 return true 893 } 894 return false 895 } 896 897 // GetSymKey returns the symmetric key associated with the given id. 898 func (w *Waku) GetSymKey(id string) ([]byte, error) { 899 w.keyMu.RLock() 900 defer w.keyMu.RUnlock() 901 if w.symKeys[id] != nil { 902 return w.symKeys[id], nil 903 } 904 return nil, fmt.Errorf("non-existent key ID") 905 } 906 907 // Subscribe installs a new message handler used for filtering, decrypting 908 // and subsequent storing of incoming messages. 909 func (w *Waku) Subscribe(f *common.Filter) (string, error) { 910 s, err := w.filters.Install(f) 911 if err != nil { 912 return s, err 913 } 914 915 err = w.updateSettingsForFilter(f) 916 if err != nil { 917 w.filters.Uninstall(s) 918 return s, err 919 } 920 return s, nil 921 } 922 923 func (w *Waku) updateSettingsForFilter(f *common.Filter) error { 924 w.settingsMu.RLock() 925 topicInterestMode := !w.settings.BloomFilterMode 926 w.settingsMu.RUnlock() 927 928 if topicInterestMode { 929 err := w.updateTopicInterest(f) 930 if err != nil { 931 return err 932 } 933 } else { 934 err := w.updateBloomFilter(f) 935 if err != nil { 936 return err 937 } 938 } 939 return nil 940 } 941 942 // updateBloomFilter recalculates the new value of bloom filter, 943 // and informs the peers if necessary. 944 func (w *Waku) updateBloomFilter(f *common.Filter) error { 945 aggregate := make([]byte, common.BloomFilterSize) 946 for _, t := range f.Topics { 947 top := common.BytesToTopic(t) 948 b := top.ToBloom() 949 aggregate = addBloom(aggregate, b) 950 } 951 952 if !common.BloomFilterMatch(w.BloomFilter(), aggregate) { 953 // existing bloom filter must be updated 954 aggregate = addBloom(w.BloomFilter(), aggregate) 955 return w.SetBloomFilter(aggregate) 956 } 957 return nil 958 } 959 960 // GetFilter returns the filter by id. 961 func (w *Waku) GetFilter(id string) *common.Filter { 962 return w.filters.Get(id) 963 } 964 965 // Unsubscribe removes an installed message handler. 966 // TODO: This does not update the bloom filter, but does update 967 // the topic interest map 968 func (w *Waku) Unsubscribe(id string) error { 969 ok := w.filters.Uninstall(id) 970 if !ok { 971 return fmt.Errorf("failed to unsubscribe: invalid ID '%s'", id) 972 } 973 if !w.settings.BloomFilterMode { 974 return w.SetTopicInterest(w.filters.AllTopics()) 975 } 976 return nil 977 } 978 979 // Unsubscribe removes an installed message handler. 980 // TODO: This does not update the bloom filter, but does update 981 // the topic interest map 982 func (w *Waku) UnsubscribeMany(ids []string) error { 983 for _, id := range ids { 984 w.logger.Debug("cleaning up filter", zap.String("id", id)) 985 ok := w.filters.Uninstall(id) 986 if !ok { 987 w.logger.Warn("could not remove filter with id", zap.String("id", id)) 988 } 989 } 990 if !w.settings.BloomFilterMode { 991 return w.SetTopicInterest(w.filters.AllTopics()) 992 } 993 return nil 994 } 995 996 // Send injects a message into the waku send queue, to be distributed in the 997 // network in the coming cycles. 998 func (w *Waku) Send(envelope *common.Envelope) error { 999 w.logger.Debug("send: sending envelope", zap.String("hash", envelope.Hash().String())) 1000 ok, err := w.add(envelope, false) 1001 if err == nil && !ok { 1002 return fmt.Errorf("failed to add envelope") 1003 } 1004 return err 1005 } 1006 1007 // Start implements node.Service, starting the background data propagation thread 1008 // of the Waku protocol. 1009 func (w *Waku) Start() error { 1010 go w.update() 1011 1012 numCPU := runtime.NumCPU() 1013 for i := 0; i < numCPU; i++ { 1014 go w.processQueue() 1015 } 1016 go w.processP2P() 1017 1018 return nil 1019 } 1020 1021 // Stop implements node.Service, stopping the background data propagation thread 1022 // of the Waku protocol. 1023 func (w *Waku) Stop() error { 1024 if w.cancelBridge != nil { 1025 close(w.cancelBridge) 1026 w.cancelBridge = nil 1027 w.bridgeWg.Wait() 1028 } 1029 close(w.quit) 1030 return nil 1031 } 1032 1033 func (w *Waku) handlePeerV0(p2pPeer *p2p.Peer, rw p2p.MsgReadWriter) error { 1034 return w.HandlePeer(v0.NewPeer(w, p2pPeer, rw, w.logger.Named("waku/peerv0"), w.stats), rw) 1035 } 1036 1037 func (w *Waku) handlePeerV1(p2pPeer *p2p.Peer, rw p2p.MsgReadWriter) error { 1038 return w.HandlePeer(v1.NewPeer(w, p2pPeer, rw, w.logger.Named("waku/peerv1"), w.stats), rw) 1039 } 1040 1041 // HandlePeer is called by the underlying P2P layer when the waku sub-protocol 1042 // connection is negotiated. 1043 func (w *Waku) HandlePeer(peer common.Peer, rw p2p.MsgReadWriter) error { 1044 w.peerMu.Lock() 1045 w.peers[peer] = struct{}{} 1046 w.peerMu.Unlock() 1047 1048 w.logger.Info("handling peer", zap.String("peerID", types.EncodeHex(peer.ID()))) 1049 1050 defer func() { 1051 w.peerMu.Lock() 1052 delete(w.peers, peer) 1053 w.peerMu.Unlock() 1054 }() 1055 1056 if err := peer.Start(); err != nil { 1057 return err 1058 } 1059 defer peer.Stop() 1060 1061 if w.rateLimiter != nil { 1062 runLoop := func(out p2p.MsgReadWriter) error { 1063 peer.SetRWWriter(out) 1064 err := peer.Run() 1065 w.logger.Info("handled peer", zap.String("peerID", types.EncodeHex(peer.ID())), zap.Error(err)) 1066 return err 1067 } 1068 return w.rateLimiter.Decorate(peer, rw, runLoop) 1069 } 1070 1071 err := peer.Run() 1072 w.logger.Info("handled peer", zap.String("peerID", types.EncodeHex(peer.ID())), zap.Error(err)) 1073 return err 1074 } 1075 1076 func (w *Waku) softBlacklisted(peerID string) bool { 1077 w.settingsMu.RLock() 1078 defer w.settingsMu.RUnlock() 1079 return w.settings.SoftBlacklistedPeerIDs[peerID] 1080 } 1081 1082 func (w *Waku) OnNewEnvelopes(envelopes []*common.Envelope, peer common.Peer) ([]common.EnvelopeError, error) { 1083 envelopeErrors := make([]common.EnvelopeError, 0) 1084 peerID := types.EncodeHex(peer.ID()) 1085 w.logger.Debug("received new envelopes", zap.Int("count", len(envelopes)), zap.String("peer", peerID)) 1086 trouble := false 1087 1088 if w.softBlacklisted(peerID) { 1089 w.logger.Debug("peer is soft blacklisted", zap.String("peer", peerID)) 1090 return nil, nil 1091 } 1092 1093 for _, env := range envelopes { 1094 w.logger.Debug("received new envelope", zap.String("peer", peerID), zap.String("hash", env.Hash().Hex())) 1095 cached, err := w.add(env, w.LightClientMode()) 1096 if err != nil { 1097 _, isTimeSyncError := err.(common.TimeSyncError) 1098 if !isTimeSyncError { 1099 trouble = true 1100 w.logger.Info("invalid envelope received", zap.String("peer", types.EncodeHex(peer.ID())), zap.Error(err)) 1101 } 1102 envelopeErrors = append(envelopeErrors, common.ErrorToEnvelopeError(env.Hash(), err)) 1103 } else if cached { 1104 peer.Mark(env) 1105 } 1106 1107 w.envelopeFeed.Send(common.EnvelopeEvent{ 1108 Event: common.EventEnvelopeReceived, 1109 Topic: env.Topic, 1110 Hash: env.Hash(), 1111 Peer: peer.EnodeID(), 1112 }) 1113 common.EnvelopesValidatedCounter.Inc() 1114 } 1115 1116 if trouble { 1117 return envelopeErrors, errors.New("received invalid envelope") 1118 } 1119 return envelopeErrors, nil 1120 } 1121 1122 func (w *Waku) OnNewP2PEnvelopes(envelopes []*common.Envelope) error { 1123 for _, envelope := range envelopes { 1124 w.postP2P(envelope) 1125 } 1126 return nil 1127 } 1128 1129 func (w *Waku) Mailserver() bool { 1130 return w.mailServer != nil 1131 } 1132 1133 func (w *Waku) OnMessagesRequest(request common.MessagesRequest, p common.Peer) error { 1134 w.mailServer.Deliver(p.ID(), request) 1135 return nil 1136 } 1137 1138 func (w *Waku) OnDeprecatedMessagesRequest(request *common.Envelope, p common.Peer) error { 1139 w.mailServer.DeliverMail(p.ID(), request) 1140 return nil 1141 } 1142 1143 func (w *Waku) OnP2PRequestCompleted(payload []byte, p common.Peer) error { 1144 msEvent, err := CreateMailServerEvent(p.EnodeID(), payload) 1145 if err != nil { 1146 return fmt.Errorf("invalid p2p request complete payload: %v", err) 1147 } 1148 1149 w.postP2P(*msEvent) 1150 return nil 1151 } 1152 1153 func (w *Waku) OnMessagesResponse(response common.MessagesResponse, p common.Peer) error { 1154 w.envelopeFeed.Send(common.EnvelopeEvent{ 1155 Batch: response.Hash, 1156 Event: common.EventBatchAcknowledged, 1157 Peer: p.EnodeID(), 1158 Data: response.Errors, 1159 }) 1160 1161 return nil 1162 } 1163 1164 func (w *Waku) OnBatchAcknowledged(batchHash gethcommon.Hash, p common.Peer) error { 1165 w.envelopeFeed.Send(common.EnvelopeEvent{ 1166 Batch: batchHash, 1167 Event: common.EventBatchAcknowledged, 1168 Peer: p.EnodeID(), 1169 }) 1170 return nil 1171 } 1172 1173 func (w *Waku) add(envelope *common.Envelope, isP2P bool) (bool, error) { 1174 return w.addAndBridge(envelope, isP2P, false) 1175 } 1176 1177 func (w *Waku) bloomMatch(envelope *common.Envelope) (bool, error) { 1178 if !common.BloomFilterMatch(w.BloomFilter(), envelope.Bloom()) { 1179 // maybe the value was recently changed, and the peers did not adjust yet. 1180 // in this case the previous value is retrieved by BloomFilterTolerance() 1181 // for a short period of peer synchronization. 1182 if !common.BloomFilterMatch(w.BloomFilterTolerance(), envelope.Bloom()) { 1183 common.EnvelopesCacheFailedCounter.WithLabelValues("no_bloom_match").Inc() 1184 return false, fmt.Errorf("envelope does not match bloom filter, hash=[%v], bloom: \n%x \n%x \n%x", 1185 envelope.Hash().Hex(), w.BloomFilter(), envelope.Bloom(), envelope.Topic) 1186 } 1187 } 1188 return true, nil 1189 } 1190 1191 func (w *Waku) topicInterestMatch(envelope *common.Envelope) (bool, error) { 1192 w.settingsMu.RLock() 1193 defer w.settingsMu.RUnlock() 1194 if w.settings.TopicInterest == nil { 1195 return false, nil 1196 } 1197 if !w.settings.TopicInterest[envelope.Topic] { 1198 if !w.settings.TopicInterestTolerance[envelope.Topic] { 1199 common.EnvelopesCacheFailedCounter.WithLabelValues("no_topic_interest_match").Inc() 1200 return false, fmt.Errorf("envelope does not match topic interest, hash=[%v], bloom: \n%x \n%x", 1201 envelope.Hash().Hex(), envelope.Bloom(), envelope.Topic) 1202 1203 } 1204 } 1205 1206 return true, nil 1207 } 1208 1209 func (w *Waku) topicInterestOrBloomMatch(envelope *common.Envelope) (bool, error) { 1210 if w.FullNode() { 1211 return true, nil 1212 } 1213 w.settingsMu.RLock() 1214 topicInterestMode := !w.settings.BloomFilterMode 1215 w.settingsMu.RUnlock() 1216 1217 if topicInterestMode { 1218 match, err := w.topicInterestMatch(envelope) 1219 if err != nil { 1220 return false, err 1221 } 1222 if match { 1223 return true, nil 1224 } 1225 } 1226 return w.bloomMatch(envelope) 1227 } 1228 1229 func (w *Waku) SetBloomFilterMode(mode bool) { 1230 w.settingsMu.Lock() 1231 w.settings.BloomFilterMode = mode 1232 w.settingsMu.Unlock() 1233 // Recalculate and notify topic interest or bloom, currently not implemented 1234 } 1235 1236 func (w *Waku) SetFullNode(set bool) { 1237 w.settingsMu.Lock() 1238 w.settings.FullNode = set 1239 w.settingsMu.Unlock() 1240 1241 // We advertise the topic interest if full node has been disabled 1242 // or bloom filter if enabled, as that's how we indicate to a peer we are a full node or not 1243 if set { 1244 w.notifyPeersAboutBloomFilterChange(w.BloomFilter()) 1245 } else { 1246 w.notifyPeersAboutTopicInterestChange(w.TopicInterest()) 1247 } 1248 } 1249 1250 // addEnvelope adds an envelope to the envelope map, used for sending 1251 func (w *Waku) addEnvelope(envelope *common.Envelope) { 1252 1253 hash := envelope.Hash() 1254 1255 w.poolMu.Lock() 1256 w.envelopes[hash] = envelope 1257 if w.expirations[envelope.Expiry] == nil { 1258 w.expirations[envelope.Expiry] = mapset.NewThreadUnsafeSet() 1259 } 1260 if !w.expirations[envelope.Expiry].Contains(hash) { 1261 w.expirations[envelope.Expiry].Add(hash) 1262 } 1263 w.poolMu.Unlock() 1264 } 1265 1266 // addAndBridge inserts a new envelope into the message pool to be distributed within the 1267 // waku network. It also inserts the envelope into the expiration pool at the 1268 // appropriate time-stamp. In case of error, connection should be dropped. 1269 // param isP2P indicates whether the message is peer-to-peer (should not be forwarded). 1270 func (w *Waku) addAndBridge(envelope *common.Envelope, isP2P bool, bridged bool) (bool, error) { 1271 now := uint32(w.timeSource().Unix()) 1272 sent := envelope.Expiry - envelope.TTL 1273 logger := w.logger.With(zap.String("hash", envelope.Hash().String()), zap.String("site", "addAndBridge"), zap.String("topic", envelope.Topic.String()), zap.Bool("isP2P", isP2P)) 1274 1275 logger.Debug("addAndBridge: processing envelope") 1276 1277 common.EnvelopesReceivedCounter.Inc() 1278 if sent > now { 1279 if sent-common.DefaultSyncAllowance > now { 1280 common.EnvelopesCacheFailedCounter.WithLabelValues("in_future").Inc() 1281 logger.Warn("envelope created in the future") 1282 return false, common.TimeSyncError(errors.New("envelope from future")) 1283 } 1284 // recalculate PoW, adjusted for the time difference, plus one second for latency 1285 envelope.CalculatePoW(sent - now + 1) 1286 } 1287 1288 if envelope.Expiry < now { 1289 if envelope.Expiry+common.DefaultSyncAllowance*2 < now { 1290 common.EnvelopesCacheFailedCounter.WithLabelValues("very_old").Inc() 1291 logger.Warn("very old envelope") 1292 return false, common.TimeSyncError(errors.New("very old envelope")) 1293 } 1294 logger.Debug("expired envelope dropped") 1295 common.EnvelopesCacheFailedCounter.WithLabelValues("expired").Inc() 1296 return false, nil // drop envelope without error 1297 } 1298 1299 if uint32(envelope.Size()) > w.MaxMessageSize() { 1300 common.EnvelopesCacheFailedCounter.WithLabelValues("oversized").Inc() 1301 return false, fmt.Errorf("huge messages are not allowed [%s][%d][%d]", envelope.Hash().String(), envelope.Size(), w.MaxMessageSize()) 1302 } 1303 1304 if envelope.PoW() < w.MinPow() { 1305 // maybe the value was recently changed, and the peers did not adjust yet. 1306 // in this case the previous value is retrieved by MinPowTolerance() 1307 // for a short period of peer synchronization. 1308 if envelope.PoW() < w.MinPowTolerance() { 1309 common.EnvelopesCacheFailedCounter.WithLabelValues("low_pow").Inc() 1310 return false, fmt.Errorf("envelope with low PoW received: PoW=%f, hash=[%s]", envelope.PoW(), envelope.Hash().String()) 1311 } 1312 } 1313 1314 match, err := w.topicInterestOrBloomMatch(envelope) 1315 if err != nil { 1316 return false, err 1317 } 1318 1319 if !match { 1320 logger.Debug("addAndBridge: no matches for envelope") 1321 return false, nil 1322 } 1323 1324 hash := envelope.Hash() 1325 1326 w.poolMu.Lock() 1327 _, alreadyCached := w.envelopes[hash] 1328 w.poolMu.Unlock() 1329 if !alreadyCached { 1330 logger.Debug("addAndBridge: adding envelope") 1331 w.addEnvelope(envelope) 1332 } 1333 1334 if alreadyCached { 1335 logger.Debug("addAndBridge: already cached") 1336 common.EnvelopesCachedCounter.WithLabelValues("hit").Inc() 1337 } else { 1338 common.EnvelopesCachedCounter.WithLabelValues("miss").Inc() 1339 common.EnvelopesSizeMeter.Observe(float64(envelope.Size())) 1340 w.postEvent(envelope, isP2P) // notify the local node about the new message 1341 if w.mailServer != nil { 1342 w.mailServer.Archive(envelope) 1343 w.envelopeFeed.Send(common.EnvelopeEvent{ 1344 Topic: envelope.Topic, 1345 Hash: envelope.Hash(), 1346 Event: common.EventMailServerEnvelopeArchived, 1347 }) 1348 } 1349 // Bridge only envelopes that are not p2p messages. 1350 // In particular, if a node is a lightweight node, 1351 // it should not bridge any envelopes. 1352 if !isP2P && !bridged && w.bridge != nil { 1353 logger.Debug("bridging envelope from Waku") 1354 _, in := w.bridge.Pipe() 1355 in <- envelope 1356 common.BridgeSent.Inc() 1357 } 1358 } 1359 return true, nil 1360 } 1361 1362 func (w *Waku) postP2P(event interface{}) { 1363 w.p2pMsgQueue <- event 1364 } 1365 1366 // postEvent queues the message for further processing. 1367 func (w *Waku) postEvent(envelope *common.Envelope, isP2P bool) { 1368 if isP2P { 1369 w.postP2P(envelope) 1370 } else { 1371 w.msgQueue <- envelope 1372 } 1373 } 1374 1375 // processQueue delivers the messages to the watchers during the lifetime of the waku node. 1376 func (w *Waku) processQueue() { 1377 for { 1378 select { 1379 case <-w.quit: 1380 return 1381 case e := <-w.msgQueue: 1382 w.filters.NotifyWatchers(e, false) 1383 w.envelopeFeed.Send(common.EnvelopeEvent{ 1384 Topic: e.Topic, 1385 Hash: e.Hash(), 1386 Event: common.EventEnvelopeAvailable, 1387 }) 1388 } 1389 } 1390 } 1391 1392 func (w *Waku) processP2P() { 1393 for { 1394 select { 1395 case <-w.quit: 1396 return 1397 case e := <-w.p2pMsgQueue: 1398 switch evn := e.(type) { 1399 case *common.Envelope: 1400 // We need to insert it first, and then remove it if not matched, 1401 // as messages are processed asynchronously 1402 w.p2pMsgIDsMu.Lock() 1403 w.p2pMsgIDs[evn.Hash()] = true 1404 w.p2pMsgIDsMu.Unlock() 1405 1406 matched := w.filters.NotifyWatchers(evn, true) 1407 1408 // If not matched we remove it 1409 if !matched { 1410 w.p2pMsgIDsMu.Lock() 1411 delete(w.p2pMsgIDs, evn.Hash()) 1412 w.p2pMsgIDsMu.Unlock() 1413 } 1414 1415 w.envelopeFeed.Send(common.EnvelopeEvent{ 1416 Topic: evn.Topic, 1417 Hash: evn.Hash(), 1418 Event: common.EventEnvelopeAvailable, 1419 }) 1420 case common.EnvelopeEvent: 1421 w.envelopeFeed.Send(evn) 1422 } 1423 } 1424 } 1425 } 1426 1427 // update loops until the lifetime of the waku node, updating its internal 1428 // state by expiring stale messages from the pool. 1429 func (w *Waku) update() { 1430 // Start a ticker to check for expirations 1431 expire := time.NewTicker(common.ExpirationCycle) 1432 1433 // Repeat updates until termination is requested 1434 for { 1435 select { 1436 case <-expire.C: 1437 w.expire() 1438 1439 case <-w.quit: 1440 return 1441 } 1442 } 1443 } 1444 1445 // expire iterates over all the expiration timestamps, removing all stale 1446 // messages from the pools. 1447 func (w *Waku) expire() { 1448 w.poolMu.Lock() 1449 defer w.poolMu.Unlock() 1450 logger := w.logger.With(zap.String("site", "expire")) 1451 1452 now := uint32(w.timeSource().Unix()) 1453 for expiry, hashSet := range w.expirations { 1454 if expiry < now { 1455 // Dump all expired messages and remove timestamp 1456 hashSet.Each(func(v interface{}) bool { 1457 logger.Debug("expiring envelope", zap.String("hash", v.(gethcommon.Hash).String())) 1458 delete(w.envelopes, v.(gethcommon.Hash)) 1459 common.EnvelopesCachedCounter.WithLabelValues("clear").Inc() 1460 w.envelopeFeed.Send(common.EnvelopeEvent{ 1461 Hash: v.(gethcommon.Hash), 1462 Event: common.EventEnvelopeExpired, 1463 }) 1464 return false 1465 }) 1466 w.expirations[expiry].Clear() 1467 delete(w.expirations, expiry) 1468 } 1469 } 1470 } 1471 1472 // Envelopes retrieves all the messages currently pooled by the node. 1473 func (w *Waku) Envelopes() []*common.Envelope { 1474 w.poolMu.RLock() 1475 defer w.poolMu.RUnlock() 1476 1477 all := make([]*common.Envelope, 0, len(w.envelopes)) 1478 for _, envelope := range w.envelopes { 1479 all = append(all, envelope) 1480 } 1481 return all 1482 } 1483 1484 // GetEnvelope retrieves an envelope from the message queue by its hash. 1485 // It returns nil if the envelope can not be found. 1486 func (w *Waku) GetEnvelope(hash gethcommon.Hash) *common.Envelope { 1487 w.poolMu.RLock() 1488 defer w.poolMu.RUnlock() 1489 return w.envelopes[hash] 1490 } 1491 1492 func (w *Waku) Version() uint { 1493 return 1 1494 } 1495 1496 // isEnvelopeCached checks if envelope with specific hash has already been received and cached. 1497 func (w *Waku) IsEnvelopeCached(hash gethcommon.Hash) bool { 1498 w.poolMu.Lock() 1499 defer w.poolMu.Unlock() 1500 1501 _, exist := w.envelopes[hash] 1502 return exist 1503 } 1504 1505 func (w *Waku) ProcessingP2PMessages() bool { 1506 w.p2pMsgIDsMu.Lock() 1507 defer w.p2pMsgIDsMu.Unlock() 1508 return len(w.p2pMsgIDs) != 0 1509 } 1510 1511 func (w *Waku) MarkP2PMessageAsProcessed(hash gethcommon.Hash) { 1512 w.p2pMsgIDsMu.Lock() 1513 defer w.p2pMsgIDsMu.Unlock() 1514 delete(w.p2pMsgIDs, hash) 1515 } 1516 1517 func (w *Waku) ClearEnvelopesCache() { 1518 w.poolMu.Lock() 1519 defer w.poolMu.Unlock() 1520 w.envelopes = make(map[gethcommon.Hash]*common.Envelope) 1521 } 1522 1523 func (w *Waku) Clean() error { 1524 w.poolMu.Lock() 1525 defer w.poolMu.Unlock() 1526 w.envelopes = make(map[gethcommon.Hash]*common.Envelope) 1527 for _, f := range w.filters.All() { 1528 f.Messages = common.NewMemoryMessageStore() 1529 } 1530 1531 return nil 1532 } 1533 1534 func (w *Waku) PeerID() peer.ID { 1535 panic("not implemented") 1536 } 1537 1538 // validatePrivateKey checks the format of the given private key. 1539 func validatePrivateKey(k *ecdsa.PrivateKey) bool { 1540 if k == nil || k.D == nil || k.D.Sign() == 0 { 1541 return false 1542 } 1543 return common.ValidatePublicKey(&k.PublicKey) 1544 } 1545 1546 // makeDeterministicID generates a deterministic ID, based on a given input 1547 func makeDeterministicID(input string, keyLen int) (id string, err error) { 1548 buf := pbkdf2.Key([]byte(input), nil, 4096, keyLen, sha256.New) 1549 if !common.ValidateDataIntegrity(buf, common.KeyIDSize) { 1550 return "", fmt.Errorf("error in GenerateDeterministicID: failed to generate key") 1551 } 1552 id = gethcommon.Bytes2Hex(buf) 1553 return id, err 1554 } 1555 1556 // toDeterministicID reviews incoming id, and transforms it to format 1557 // expected internally be private key store. Originally, public keys 1558 // were used as keys, now random keys are being used. And in order to 1559 // make it easier to consume, we now allow both random IDs and public 1560 // keys to be passed. 1561 func toDeterministicID(id string, expectedLen int) (string, error) { 1562 if len(id) != (expectedLen * 2) { // we received hex key, so number of chars in id is doubled 1563 var err error 1564 id, err = makeDeterministicID(id, expectedLen) 1565 if err != nil { 1566 return "", err 1567 } 1568 } 1569 1570 return id, nil 1571 } 1572 1573 func addBloom(a, b []byte) []byte { 1574 c := make([]byte, common.BloomFilterSize) 1575 for i := 0; i < common.BloomFilterSize; i++ { 1576 c[i] = a[i] | b[i] 1577 } 1578 return c 1579 }