github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/whisper/whisperv6/whisper.go (about) 1 // Copyright 2016 The Spectrum Authors 2 // This file is part of the Spectrum library. 3 // 4 // The Spectrum 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 Spectrum 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 Spectrum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package whisperv6 18 19 import ( 20 "bytes" 21 "crypto/ecdsa" 22 crand "crypto/rand" 23 "crypto/sha256" 24 "fmt" 25 "math" 26 "runtime" 27 "sync" 28 "time" 29 30 "github.com/SmartMeshFoundation/Spectrum/common" 31 "github.com/SmartMeshFoundation/Spectrum/crypto" 32 "github.com/SmartMeshFoundation/Spectrum/log" 33 "github.com/SmartMeshFoundation/Spectrum/p2p" 34 "github.com/SmartMeshFoundation/Spectrum/rlp" 35 "github.com/SmartMeshFoundation/Spectrum/rpc" 36 "github.com/syndtr/goleveldb/leveldb/errors" 37 "golang.org/x/crypto/pbkdf2" 38 "golang.org/x/sync/syncmap" 39 set "gopkg.in/fatih/set.v0" 40 ) 41 42 type Statistics struct { 43 messagesCleared int 44 memoryCleared int 45 memoryUsed int 46 cycles int 47 totalMessagesCleared int 48 } 49 50 const ( 51 minPowIdx = iota // Minimal PoW required by the whisper node 52 maxMsgSizeIdx = iota // Maximal message length allowed by the whisper node 53 overflowIdx = iota // Indicator of message queue overflow 54 ) 55 56 // Whisper represents a dark communication interface through the Ethereum 57 // network, using its very own P2P communication layer. 58 type Whisper struct { 59 protocol p2p.Protocol // Protocol description and parameters 60 filters *Filters // Message filters installed with Subscribe function 61 62 privateKeys map[string]*ecdsa.PrivateKey // Private key storage 63 symKeys map[string][]byte // Symmetric key storage 64 keyMu sync.RWMutex // Mutex associated with key storages 65 66 poolMu sync.RWMutex // Mutex to sync the message and expiration pools 67 envelopes map[common.Hash]*Envelope // Pool of envelopes currently tracked by this node 68 expirations map[uint32]*set.SetNonTS // Message expiration pool 69 70 peerMu sync.RWMutex // Mutex to sync the active peer set 71 peers map[*Peer]struct{} // Set of currently active peers 72 73 messageQueue chan *Envelope // Message queue for normal whisper messages 74 p2pMsgQueue chan *Envelope // Message queue for peer-to-peer messages (not to be forwarded any further) 75 quit chan struct{} // Channel used for graceful exit 76 77 settings syncmap.Map // holds configuration settings that can be dynamically changed 78 79 reactionAllowance int // maximum time in seconds allowed to process the whisper-related messages 80 81 statsMu sync.Mutex // guard stats 82 stats Statistics // Statistics of whisper node 83 84 mailServer MailServer // MailServer interface 85 } 86 87 // New creates a Whisper client ready to communicate through the Ethereum P2P network. 88 func New(cfg *Config) *Whisper { 89 if cfg == nil { 90 cfg = &DefaultConfig 91 } 92 93 whisper := &Whisper{ 94 privateKeys: make(map[string]*ecdsa.PrivateKey), 95 symKeys: make(map[string][]byte), 96 envelopes: make(map[common.Hash]*Envelope), 97 expirations: make(map[uint32]*set.SetNonTS), 98 peers: make(map[*Peer]struct{}), 99 messageQueue: make(chan *Envelope, messageQueueLimit), 100 p2pMsgQueue: make(chan *Envelope, messageQueueLimit), 101 quit: make(chan struct{}), 102 reactionAllowance: SynchAllowance, 103 } 104 105 whisper.filters = NewFilters(whisper) 106 107 whisper.settings.Store(minPowIdx, cfg.MinimumAcceptedPOW) 108 whisper.settings.Store(maxMsgSizeIdx, cfg.MaxMessageSize) 109 whisper.settings.Store(overflowIdx, false) 110 111 // p2p whisper sub protocol handler 112 whisper.protocol = p2p.Protocol{ 113 Name: ProtocolName, 114 Version: uint(ProtocolVersion), 115 Length: NumberOfMessageCodes, 116 Run: whisper.HandlePeer, 117 NodeInfo: func() interface{} { 118 return map[string]interface{}{ 119 "version": ProtocolVersionStr, 120 "maxMessageSize": whisper.MaxMessageSize(), 121 "minimumPoW": whisper.MinPow(), 122 } 123 }, 124 } 125 126 return whisper 127 } 128 129 func (w *Whisper) MinPow() float64 { 130 val, _ := w.settings.Load(minPowIdx) 131 return val.(float64) 132 } 133 134 // MaxMessageSize returns the maximum accepted message size. 135 func (w *Whisper) MaxMessageSize() uint32 { 136 val, _ := w.settings.Load(maxMsgSizeIdx) 137 return val.(uint32) 138 } 139 140 // Overflow returns an indication if the message queue is full. 141 func (w *Whisper) Overflow() bool { 142 val, _ := w.settings.Load(overflowIdx) 143 return val.(bool) 144 } 145 146 // APIs returns the RPC descriptors the Whisper implementation offers 147 func (w *Whisper) APIs() []rpc.API { 148 return []rpc.API{ 149 { 150 Namespace: ProtocolName, 151 Version: ProtocolVersionStr, 152 Service: NewPublicWhisperAPI(w), 153 Public: true, 154 }, 155 } 156 } 157 158 // RegisterServer registers MailServer interface. 159 // MailServer will process all the incoming messages with p2pRequestCode. 160 func (w *Whisper) RegisterServer(server MailServer) { 161 w.mailServer = server 162 } 163 164 // Protocols returns the whisper sub-protocols ran by this particular client. 165 func (w *Whisper) Protocols() []p2p.Protocol { 166 return []p2p.Protocol{w.protocol} 167 } 168 169 // Version returns the whisper sub-protocols version number. 170 func (w *Whisper) Version() uint { 171 return w.protocol.Version 172 } 173 174 // SetMaxMessageSize sets the maximal message size allowed by this node 175 func (w *Whisper) SetMaxMessageSize(size uint32) error { 176 if size > MaxMessageSize { 177 return fmt.Errorf("message size too large [%d>%d]", size, MaxMessageSize) 178 } 179 w.settings.Store(maxMsgSizeIdx, size) 180 return nil 181 } 182 183 // SetMinimumPoW sets the minimal PoW required by this node 184 func (w *Whisper) SetMinimumPoW(val float64) error { 185 if val < 0.0 { 186 return fmt.Errorf("invalid PoW: %f", val) 187 } 188 189 w.notifyPeersAboutPowRequirementChange(val) 190 191 go func() { 192 // allow some time before all the peers have processed the notification 193 time.Sleep(time.Duration(w.reactionAllowance) * time.Second) 194 w.settings.Store(minPowIdx, val) 195 }() 196 197 return nil 198 } 199 200 // SetMinimumPoW sets the minimal PoW in test environment 201 func (w *Whisper) SetMinimumPowTest(val float64) { 202 w.notifyPeersAboutPowRequirementChange(val) 203 w.settings.Store(minPowIdx, val) 204 } 205 206 func (w *Whisper) notifyPeersAboutPowRequirementChange(pow float64) { 207 arr := make([]*Peer, len(w.peers)) 208 i := 0 209 210 w.peerMu.Lock() 211 for p := range w.peers { 212 arr[i] = p 213 i++ 214 } 215 w.peerMu.Unlock() 216 217 for _, p := range arr { 218 err := p.notifyAboutPowRequirementChange(pow) 219 if err != nil { 220 // allow one retry 221 err = p.notifyAboutPowRequirementChange(pow) 222 } 223 if err != nil { 224 log.Warn("oversized message received", "peer", p.ID(), "error", err) 225 } 226 } 227 } 228 229 // getPeer retrieves peer by ID 230 func (w *Whisper) getPeer(peerID []byte) (*Peer, error) { 231 w.peerMu.Lock() 232 defer w.peerMu.Unlock() 233 for p := range w.peers { 234 id := p.peer.ID() 235 if bytes.Equal(peerID, id[:]) { 236 return p, nil 237 } 238 } 239 return nil, fmt.Errorf("Could not find peer with ID: %x", peerID) 240 } 241 242 // AllowP2PMessagesFromPeer marks specific peer trusted, 243 // which will allow it to send historic (expired) messages. 244 func (w *Whisper) AllowP2PMessagesFromPeer(peerID []byte) error { 245 p, err := w.getPeer(peerID) 246 if err != nil { 247 return err 248 } 249 p.trusted = true 250 return nil 251 } 252 253 // RequestHistoricMessages sends a message with p2pRequestCode to a specific peer, 254 // which is known to implement MailServer interface, and is supposed to process this 255 // request and respond with a number of peer-to-peer messages (possibly expired), 256 // which are not supposed to be forwarded any further. 257 // The whisper protocol is agnostic of the format and contents of envelope. 258 func (w *Whisper) RequestHistoricMessages(peerID []byte, envelope *Envelope) error { 259 p, err := w.getPeer(peerID) 260 if err != nil { 261 return err 262 } 263 p.trusted = true 264 return p2p.Send(p.ws, p2pRequestCode, envelope) 265 } 266 267 // SendP2PMessage sends a peer-to-peer message to a specific peer. 268 func (w *Whisper) SendP2PMessage(peerID []byte, envelope *Envelope) error { 269 p, err := w.getPeer(peerID) 270 if err != nil { 271 return err 272 } 273 return w.SendP2PDirect(p, envelope) 274 } 275 276 // SendP2PDirect sends a peer-to-peer message to a specific peer. 277 func (w *Whisper) SendP2PDirect(peer *Peer, envelope *Envelope) error { 278 return p2p.Send(peer.ws, p2pMessageCode, envelope) 279 } 280 281 // NewKeyPair generates a new cryptographic identity for the client, and injects 282 // it into the known identities for message decryption. Returns ID of the new key pair. 283 func (w *Whisper) NewKeyPair() (string, error) { 284 key, err := crypto.GenerateKey() 285 if err != nil || !validatePrivateKey(key) { 286 key, err = crypto.GenerateKey() // retry once 287 } 288 if err != nil { 289 return "", err 290 } 291 if !validatePrivateKey(key) { 292 return "", fmt.Errorf("failed to generate valid key") 293 } 294 295 id, err := GenerateRandomID() 296 if err != nil { 297 return "", fmt.Errorf("failed to generate ID: %s", err) 298 } 299 300 w.keyMu.Lock() 301 defer w.keyMu.Unlock() 302 303 if w.privateKeys[id] != nil { 304 return "", fmt.Errorf("failed to generate unique ID") 305 } 306 w.privateKeys[id] = key 307 return id, nil 308 } 309 310 // DeleteKeyPair deletes the specified key if it exists. 311 func (w *Whisper) DeleteKeyPair(key string) bool { 312 w.keyMu.Lock() 313 defer w.keyMu.Unlock() 314 315 if w.privateKeys[key] != nil { 316 delete(w.privateKeys, key) 317 return true 318 } 319 return false 320 } 321 322 // AddKeyPair imports a asymmetric private key and returns it identifier. 323 func (w *Whisper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) { 324 id, err := GenerateRandomID() 325 if err != nil { 326 return "", fmt.Errorf("failed to generate ID: %s", err) 327 } 328 329 w.keyMu.Lock() 330 w.privateKeys[id] = key 331 w.keyMu.Unlock() 332 333 return id, nil 334 } 335 336 // HasKeyPair checks if the the whisper node is configured with the private key 337 // of the specified public pair. 338 func (w *Whisper) HasKeyPair(id string) bool { 339 w.keyMu.RLock() 340 defer w.keyMu.RUnlock() 341 return w.privateKeys[id] != nil 342 } 343 344 // GetPrivateKey retrieves the private key of the specified identity. 345 func (w *Whisper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) { 346 w.keyMu.RLock() 347 defer w.keyMu.RUnlock() 348 key := w.privateKeys[id] 349 if key == nil { 350 return nil, fmt.Errorf("invalid id") 351 } 352 return key, nil 353 } 354 355 // GenerateSymKey generates a random symmetric key and stores it under id, 356 // which is then returned. Will be used in the future for session key exchange. 357 func (w *Whisper) GenerateSymKey() (string, error) { 358 key := make([]byte, aesKeyLength) 359 _, err := crand.Read(key) 360 if err != nil { 361 return "", err 362 } else if !validateSymmetricKey(key) { 363 return "", fmt.Errorf("error in GenerateSymKey: crypto/rand failed to generate random data") 364 } 365 366 id, err := GenerateRandomID() 367 if err != nil { 368 return "", fmt.Errorf("failed to generate ID: %s", err) 369 } 370 371 w.keyMu.Lock() 372 defer w.keyMu.Unlock() 373 374 if w.symKeys[id] != nil { 375 return "", fmt.Errorf("failed to generate unique ID") 376 } 377 w.symKeys[id] = key 378 return id, nil 379 } 380 381 // AddSymKeyDirect stores the key, and returns its id. 382 func (w *Whisper) AddSymKeyDirect(key []byte) (string, error) { 383 if len(key) != aesKeyLength { 384 return "", fmt.Errorf("wrong key size: %d", len(key)) 385 } 386 387 id, err := GenerateRandomID() 388 if err != nil { 389 return "", fmt.Errorf("failed to generate ID: %s", err) 390 } 391 392 w.keyMu.Lock() 393 defer w.keyMu.Unlock() 394 395 if w.symKeys[id] != nil { 396 return "", fmt.Errorf("failed to generate unique ID") 397 } 398 w.symKeys[id] = key 399 return id, nil 400 } 401 402 // AddSymKeyFromPassword generates the key from password, stores it, and returns its id. 403 func (w *Whisper) AddSymKeyFromPassword(password string) (string, error) { 404 id, err := GenerateRandomID() 405 if err != nil { 406 return "", fmt.Errorf("failed to generate ID: %s", err) 407 } 408 if w.HasSymKey(id) { 409 return "", fmt.Errorf("failed to generate unique ID") 410 } 411 412 // kdf should run no less than 0.1 seconds on an average computer, 413 // because it's an once in a session experience 414 derived := pbkdf2.Key([]byte(password), nil, 65356, aesKeyLength, sha256.New) 415 if err != nil { 416 return "", err 417 } 418 419 w.keyMu.Lock() 420 defer w.keyMu.Unlock() 421 422 // double check is necessary, because deriveKeyMaterial() is very slow 423 if w.symKeys[id] != nil { 424 return "", fmt.Errorf("critical error: failed to generate unique ID") 425 } 426 w.symKeys[id] = derived 427 return id, nil 428 } 429 430 // HasSymKey returns true if there is a key associated with the given id. 431 // Otherwise returns false. 432 func (w *Whisper) HasSymKey(id string) bool { 433 w.keyMu.RLock() 434 defer w.keyMu.RUnlock() 435 return w.symKeys[id] != nil 436 } 437 438 // DeleteSymKey deletes the key associated with the name string if it exists. 439 func (w *Whisper) DeleteSymKey(id string) bool { 440 w.keyMu.Lock() 441 defer w.keyMu.Unlock() 442 if w.symKeys[id] != nil { 443 delete(w.symKeys, id) 444 return true 445 } 446 return false 447 } 448 449 // GetSymKey returns the symmetric key associated with the given id. 450 func (w *Whisper) GetSymKey(id string) ([]byte, error) { 451 w.keyMu.RLock() 452 defer w.keyMu.RUnlock() 453 if w.symKeys[id] != nil { 454 return w.symKeys[id], nil 455 } 456 return nil, fmt.Errorf("non-existent key ID") 457 } 458 459 // Subscribe installs a new message handler used for filtering, decrypting 460 // and subsequent storing of incoming messages. 461 func (w *Whisper) Subscribe(f *Filter) (string, error) { 462 return w.filters.Install(f) 463 } 464 465 // GetFilter returns the filter by id. 466 func (w *Whisper) GetFilter(id string) *Filter { 467 return w.filters.Get(id) 468 } 469 470 // Unsubscribe removes an installed message handler. 471 func (w *Whisper) Unsubscribe(id string) error { 472 ok := w.filters.Uninstall(id) 473 if !ok { 474 return fmt.Errorf("Unsubscribe: Invalid ID") 475 } 476 return nil 477 } 478 479 // Send injects a message into the whisper send queue, to be distributed in the 480 // network in the coming cycles. 481 func (w *Whisper) Send(envelope *Envelope) error { 482 ok, err := w.add(envelope) 483 if err != nil { 484 return err 485 } 486 if !ok { 487 return fmt.Errorf("failed to add envelope") 488 } 489 return err 490 } 491 492 // Start implements node.Service, starting the background data propagation thread 493 // of the Whisper protocol. 494 func (w *Whisper) Start(*p2p.Server) error { 495 log.Info("started whisper v." + ProtocolVersionStr) 496 go w.update() 497 498 numCPU := runtime.NumCPU() 499 for i := 0; i < numCPU; i++ { 500 go w.processQueue() 501 } 502 503 return nil 504 } 505 506 // Stop implements node.Service, stopping the background data propagation thread 507 // of the Whisper protocol. 508 func (w *Whisper) Stop() error { 509 close(w.quit) 510 log.Info("whisper stopped") 511 return nil 512 } 513 514 // HandlePeer is called by the underlying P2P layer when the whisper sub-protocol 515 // connection is negotiated. 516 func (wh *Whisper) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error { 517 // Create the new peer and start tracking it 518 whisperPeer := newPeer(wh, peer, rw) 519 520 wh.peerMu.Lock() 521 wh.peers[whisperPeer] = struct{}{} 522 wh.peerMu.Unlock() 523 524 defer func() { 525 wh.peerMu.Lock() 526 delete(wh.peers, whisperPeer) 527 wh.peerMu.Unlock() 528 }() 529 530 // Run the peer handshake and state updates 531 if err := whisperPeer.handshake(); err != nil { 532 return err 533 } 534 whisperPeer.start() 535 defer whisperPeer.stop() 536 537 return wh.runMessageLoop(whisperPeer, rw) 538 } 539 540 // runMessageLoop reads and processes inbound messages directly to merge into client-global state. 541 func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { 542 for { 543 // fetch the next packet 544 packet, err := rw.ReadMsg() 545 if err != nil { 546 log.Warn("message loop", "peer", p.peer.ID(), "err", err) 547 return err 548 } 549 if packet.Size > wh.MaxMessageSize() { 550 log.Warn("oversized message received", "peer", p.peer.ID()) 551 return errors.New("oversized message received") 552 } 553 554 switch packet.Code { 555 case statusCode: 556 // this should not happen, but no need to panic; just ignore this message. 557 log.Warn("unxepected status message received", "peer", p.peer.ID()) 558 case messagesCode: 559 // decode the contained envelopes 560 var envelopes []*Envelope 561 if err := packet.Decode(&envelopes); err != nil { 562 log.Warn("failed to decode envelopes, peer will be disconnected", "peer", p.peer.ID(), "err", err) 563 return errors.New("invalid envelopes") 564 } 565 566 trouble := false 567 for _, env := range envelopes { 568 cached, err := wh.add(env) 569 if err != nil { 570 trouble = true 571 log.Error("bad envelope received, peer will be disconnected", "peer", p.peer.ID(), "err", err) 572 } 573 if cached { 574 p.mark(env) 575 } 576 } 577 578 if trouble { 579 return errors.New("invalid envelope") 580 } 581 case powRequirementCode: 582 s := rlp.NewStream(packet.Payload, uint64(packet.Size)) 583 i, err := s.Uint() 584 if err != nil { 585 log.Warn("failed to decode powRequirementCode message, peer will be disconnected", "peer", p.peer.ID(), "err", err) 586 return errors.New("invalid powRequirementCode message") 587 } 588 f := math.Float64frombits(i) 589 if math.IsInf(f, 0) || math.IsNaN(f) || f < 0.0 { 590 log.Warn("invalid value in powRequirementCode message, peer will be disconnected", "peer", p.peer.ID(), "err", err) 591 return errors.New("invalid value in powRequirementCode message") 592 } 593 p.powRequirement = f 594 case bloomFilterExCode: 595 // to be implemented 596 case p2pMessageCode: 597 // peer-to-peer message, sent directly to peer bypassing PoW checks, etc. 598 // this message is not supposed to be forwarded to other peers, and 599 // therefore might not satisfy the PoW, expiry and other requirements. 600 // these messages are only accepted from the trusted peer. 601 if p.trusted { 602 var envelope Envelope 603 if err := packet.Decode(&envelope); err != nil { 604 log.Warn("failed to decode direct message, peer will be disconnected", "peer", p.peer.ID(), "err", err) 605 return errors.New("invalid direct message") 606 } 607 wh.postEvent(&envelope, true) 608 } 609 case p2pRequestCode: 610 // Must be processed if mail server is implemented. Otherwise ignore. 611 if wh.mailServer != nil { 612 var request Envelope 613 if err := packet.Decode(&request); err != nil { 614 log.Warn("failed to decode p2p request message, peer will be disconnected", "peer", p.peer.ID(), "err", err) 615 return errors.New("invalid p2p request") 616 } 617 wh.mailServer.DeliverMail(p, &request) 618 } 619 default: 620 // New message types might be implemented in the future versions of Whisper. 621 // For forward compatibility, just ignore. 622 } 623 624 packet.Discard() 625 } 626 } 627 628 // add inserts a new envelope into the message pool to be distributed within the 629 // whisper network. It also inserts the envelope into the expiration pool at the 630 // appropriate time-stamp. In case of error, connection should be dropped. 631 func (wh *Whisper) add(envelope *Envelope) (bool, error) { 632 now := uint32(time.Now().Unix()) 633 sent := envelope.Expiry - envelope.TTL 634 635 if sent > now { 636 if sent-SynchAllowance > now { 637 return false, fmt.Errorf("envelope created in the future [%x]", envelope.Hash()) 638 } else { 639 // recalculate PoW, adjusted for the time difference, plus one second for latency 640 envelope.calculatePoW(sent - now + 1) 641 } 642 } 643 644 if envelope.Expiry < now { 645 if envelope.Expiry+SynchAllowance*2 < now { 646 return false, fmt.Errorf("very old message") 647 } else { 648 log.Debug("expired envelope dropped", "hash", envelope.Hash().Hex()) 649 return false, nil // drop envelope without error 650 } 651 } 652 653 if uint32(envelope.size()) > wh.MaxMessageSize() { 654 return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash()) 655 } 656 657 if envelope.PoW() < wh.MinPow() { 658 log.Debug("envelope with low PoW dropped", "PoW", envelope.PoW(), "hash", envelope.Hash().Hex()) 659 return false, nil // drop envelope without error for now 660 661 // once the status message includes the PoW requirement, an error should be returned here: 662 //return false, fmt.Errorf("envelope with low PoW dropped: PoW=%f, hash=[%v]", envelope.PoW(), envelope.Hash().Hex()) 663 } 664 665 hash := envelope.Hash() 666 667 wh.poolMu.Lock() 668 _, alreadyCached := wh.envelopes[hash] 669 if !alreadyCached { 670 wh.envelopes[hash] = envelope 671 if wh.expirations[envelope.Expiry] == nil { 672 wh.expirations[envelope.Expiry] = set.NewNonTS() 673 } 674 if !wh.expirations[envelope.Expiry].Has(hash) { 675 wh.expirations[envelope.Expiry].Add(hash) 676 } 677 } 678 wh.poolMu.Unlock() 679 680 if alreadyCached { 681 log.Trace("whisper envelope already cached", "hash", envelope.Hash().Hex()) 682 } else { 683 log.Trace("cached whisper envelope", "hash", envelope.Hash().Hex()) 684 wh.statsMu.Lock() 685 wh.stats.memoryUsed += envelope.size() 686 wh.statsMu.Unlock() 687 wh.postEvent(envelope, false) // notify the local node about the new message 688 if wh.mailServer != nil { 689 wh.mailServer.Archive(envelope) 690 } 691 } 692 return true, nil 693 } 694 695 // postEvent queues the message for further processing. 696 func (w *Whisper) postEvent(envelope *Envelope, isP2P bool) { 697 if isP2P { 698 w.p2pMsgQueue <- envelope 699 } else { 700 w.checkOverflow() 701 w.messageQueue <- envelope 702 } 703 } 704 705 // checkOverflow checks if message queue overflow occurs and reports it if necessary. 706 func (w *Whisper) checkOverflow() { 707 queueSize := len(w.messageQueue) 708 709 if queueSize == messageQueueLimit { 710 if !w.Overflow() { 711 w.settings.Store(overflowIdx, true) 712 log.Warn("message queue overflow") 713 } 714 } else if queueSize <= messageQueueLimit/2 { 715 if w.Overflow() { 716 w.settings.Store(overflowIdx, false) 717 log.Warn("message queue overflow fixed (back to normal)") 718 } 719 } 720 } 721 722 // processQueue delivers the messages to the watchers during the lifetime of the whisper node. 723 func (w *Whisper) processQueue() { 724 var e *Envelope 725 for { 726 select { 727 case <-w.quit: 728 return 729 730 case e = <-w.messageQueue: 731 w.filters.NotifyWatchers(e, false) 732 733 case e = <-w.p2pMsgQueue: 734 w.filters.NotifyWatchers(e, true) 735 } 736 } 737 } 738 739 // update loops until the lifetime of the whisper node, updating its internal 740 // state by expiring stale messages from the pool. 741 func (w *Whisper) update() { 742 // Start a ticker to check for expirations 743 expire := time.NewTicker(expirationCycle) 744 745 // Repeat updates until termination is requested 746 for { 747 select { 748 case <-expire.C: 749 w.expire() 750 751 case <-w.quit: 752 return 753 } 754 } 755 } 756 757 // expire iterates over all the expiration timestamps, removing all stale 758 // messages from the pools. 759 func (w *Whisper) expire() { 760 w.poolMu.Lock() 761 defer w.poolMu.Unlock() 762 763 w.statsMu.Lock() 764 defer w.statsMu.Unlock() 765 w.stats.reset() 766 now := uint32(time.Now().Unix()) 767 for expiry, hashSet := range w.expirations { 768 if expiry < now { 769 // Dump all expired messages and remove timestamp 770 hashSet.Each(func(v interface{}) bool { 771 sz := w.envelopes[v.(common.Hash)].size() 772 delete(w.envelopes, v.(common.Hash)) 773 w.stats.messagesCleared++ 774 w.stats.memoryCleared += sz 775 w.stats.memoryUsed -= sz 776 return true 777 }) 778 w.expirations[expiry].Clear() 779 delete(w.expirations, expiry) 780 } 781 } 782 } 783 784 // Stats returns the whisper node statistics. 785 func (w *Whisper) Stats() Statistics { 786 w.statsMu.Lock() 787 defer w.statsMu.Unlock() 788 789 return w.stats 790 } 791 792 // Envelopes retrieves all the messages currently pooled by the node. 793 func (w *Whisper) Envelopes() []*Envelope { 794 w.poolMu.RLock() 795 defer w.poolMu.RUnlock() 796 797 all := make([]*Envelope, 0, len(w.envelopes)) 798 for _, envelope := range w.envelopes { 799 all = append(all, envelope) 800 } 801 return all 802 } 803 804 // Messages iterates through all currently floating envelopes 805 // and retrieves all the messages, that this filter could decrypt. 806 func (w *Whisper) Messages(id string) []*ReceivedMessage { 807 result := make([]*ReceivedMessage, 0) 808 w.poolMu.RLock() 809 defer w.poolMu.RUnlock() 810 811 if filter := w.filters.Get(id); filter != nil { 812 for _, env := range w.envelopes { 813 msg := filter.processEnvelope(env) 814 if msg != nil { 815 result = append(result, msg) 816 } 817 } 818 } 819 return result 820 } 821 822 // isEnvelopeCached checks if envelope with specific hash has already been received and cached. 823 func (w *Whisper) isEnvelopeCached(hash common.Hash) bool { 824 w.poolMu.Lock() 825 defer w.poolMu.Unlock() 826 827 _, exist := w.envelopes[hash] 828 return exist 829 } 830 831 // reset resets the node's statistics after each expiry cycle. 832 func (s *Statistics) reset() { 833 s.cycles++ 834 s.totalMessagesCleared += s.messagesCleared 835 836 s.memoryCleared = 0 837 s.messagesCleared = 0 838 } 839 840 // ValidatePublicKey checks the format of the given public key. 841 func ValidatePublicKey(k *ecdsa.PublicKey) bool { 842 return k != nil && k.X != nil && k.Y != nil && k.X.Sign() != 0 && k.Y.Sign() != 0 843 } 844 845 // validatePrivateKey checks the format of the given private key. 846 func validatePrivateKey(k *ecdsa.PrivateKey) bool { 847 if k == nil || k.D == nil || k.D.Sign() == 0 { 848 return false 849 } 850 return ValidatePublicKey(&k.PublicKey) 851 } 852 853 // validateSymmetricKey returns false if the key contains all zeros 854 func validateSymmetricKey(k []byte) bool { 855 return len(k) > 0 && !containsOnlyZeros(k) 856 } 857 858 // containsOnlyZeros checks if the data contain only zeros. 859 func containsOnlyZeros(data []byte) bool { 860 for _, b := range data { 861 if b != 0 { 862 return false 863 } 864 } 865 return true 866 } 867 868 // bytesToUintLittleEndian converts the slice to 64-bit unsigned integer. 869 func bytesToUintLittleEndian(b []byte) (res uint64) { 870 mul := uint64(1) 871 for i := 0; i < len(b); i++ { 872 res += uint64(b[i]) * mul 873 mul *= 256 874 } 875 return res 876 } 877 878 // BytesToUintBigEndian converts the slice to 64-bit unsigned integer. 879 func BytesToUintBigEndian(b []byte) (res uint64) { 880 for i := 0; i < len(b); i++ { 881 res *= 256 882 res += uint64(b[i]) 883 } 884 return res 885 } 886 887 // GenerateRandomID generates a random string, which is then returned to be used as a key id 888 func GenerateRandomID() (id string, err error) { 889 buf := make([]byte, keyIdSize) 890 _, err = crand.Read(buf) 891 if err != nil { 892 return "", err 893 } 894 if !validateSymmetricKey(buf) { 895 return "", fmt.Errorf("error in generateRandomID: crypto/rand failed to generate random data") 896 } 897 id = common.Bytes2Hex(buf) 898 return id, err 899 }