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