github.com/luckypickle/go-ethereum-vet@v1.14.2/whisper/whisperv5/whisper.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package 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 mapset "github.com/deckarep/golang-set" 30 "github.com/luckypickle/go-ethereum-vet/common" 31 "github.com/luckypickle/go-ethereum-vet/crypto" 32 "github.com/luckypickle/go-ethereum-vet/log" 33 "github.com/luckypickle/go-ethereum-vet/p2p" 34 "github.com/luckypickle/go-ethereum-vet/rpc" 35 "github.com/syndtr/goleveldb/leveldb/errors" 36 "golang.org/x/crypto/pbkdf2" 37 "golang.org/x/sync/syncmap" 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]mapset.Set // 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]mapset.Set), 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 (w *Whisper) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error { 473 // Create the new peer and start tracking it 474 whisperPeer := newPeer(w, peer, rw) 475 476 w.peerMu.Lock() 477 w.peers[whisperPeer] = struct{}{} 478 w.peerMu.Unlock() 479 480 defer func() { 481 w.peerMu.Lock() 482 delete(w.peers, whisperPeer) 483 w.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 w.runMessageLoop(whisperPeer, rw) 494 } 495 496 // runMessageLoop reads and processes inbound messages directly to merge into client-global state. 497 func (w *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.Info("message loop", "peer", p.peer.ID(), "err", err) 503 return err 504 } 505 if packet.Size > w.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 := w.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 w.postEvent(&envelope, true) 541 } 542 case p2pRequestCode: 543 // Must be processed if mail server is implemented. Otherwise ignore. 544 if w.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 w.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 (w *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 } 572 // recalculate PoW, adjusted for the time difference, plus one second for latency 573 envelope.calculatePoW(sent - now + 1) 574 } 575 576 if envelope.Expiry < now { 577 if envelope.Expiry+SynchAllowance*2 < now { 578 return false, fmt.Errorf("very old message") 579 } 580 log.Debug("expired envelope dropped", "hash", envelope.Hash().Hex()) 581 return false, nil // drop envelope without error 582 } 583 584 if uint32(envelope.size()) > w.MaxMessageSize() { 585 return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash()) 586 } 587 588 if len(envelope.Version) > 4 { 589 return false, fmt.Errorf("oversized version [%x]", envelope.Hash()) 590 } 591 592 aesNonceSize := len(envelope.AESNonce) 593 if aesNonceSize != 0 && aesNonceSize != AESNonceLength { 594 // the standard AES GCM nonce size is 12 bytes, 595 // but constant gcmStandardNonceSize cannot be accessed (not exported) 596 return false, fmt.Errorf("wrong size of AESNonce: %d bytes [env: %x]", aesNonceSize, envelope.Hash()) 597 } 598 599 if envelope.PoW() < w.MinPow() { 600 log.Debug("envelope with low PoW dropped", "PoW", envelope.PoW(), "hash", envelope.Hash().Hex()) 601 return false, nil // drop envelope without error 602 } 603 604 hash := envelope.Hash() 605 606 w.poolMu.Lock() 607 _, alreadyCached := w.envelopes[hash] 608 if !alreadyCached { 609 w.envelopes[hash] = envelope 610 if w.expirations[envelope.Expiry] == nil { 611 w.expirations[envelope.Expiry] = mapset.NewThreadUnsafeSet() 612 } 613 if !w.expirations[envelope.Expiry].Contains(hash) { 614 w.expirations[envelope.Expiry].Add(hash) 615 } 616 } 617 w.poolMu.Unlock() 618 619 if alreadyCached { 620 log.Trace("whisper envelope already cached", "hash", envelope.Hash().Hex()) 621 } else { 622 log.Trace("cached whisper envelope", "hash", envelope.Hash().Hex()) 623 w.statsMu.Lock() 624 w.stats.memoryUsed += envelope.size() 625 w.statsMu.Unlock() 626 w.postEvent(envelope, false) // notify the local node about the new message 627 if w.mailServer != nil { 628 w.mailServer.Archive(envelope) 629 } 630 } 631 return true, nil 632 } 633 634 // postEvent queues the message for further processing. 635 func (w *Whisper) postEvent(envelope *Envelope, isP2P bool) { 636 // if the version of incoming message is higher than 637 // currently supported version, we can not decrypt it, 638 // and therefore just ignore this message 639 if envelope.Ver() <= EnvelopeVersion { 640 if isP2P { 641 w.p2pMsgQueue <- envelope 642 } else { 643 w.checkOverflow() 644 w.messageQueue <- envelope 645 } 646 } 647 } 648 649 // checkOverflow checks if message queue overflow occurs and reports it if necessary. 650 func (w *Whisper) checkOverflow() { 651 queueSize := len(w.messageQueue) 652 653 if queueSize == messageQueueLimit { 654 if !w.Overflow() { 655 w.settings.Store(overflowIdx, true) 656 log.Warn("message queue overflow") 657 } 658 } else if queueSize <= messageQueueLimit/2 { 659 if w.Overflow() { 660 w.settings.Store(overflowIdx, false) 661 log.Warn("message queue overflow fixed (back to normal)") 662 } 663 } 664 } 665 666 // processQueue delivers the messages to the watchers during the lifetime of the whisper node. 667 func (w *Whisper) processQueue() { 668 var e *Envelope 669 for { 670 select { 671 case <-w.quit: 672 return 673 674 case e = <-w.messageQueue: 675 w.filters.NotifyWatchers(e, false) 676 677 case e = <-w.p2pMsgQueue: 678 w.filters.NotifyWatchers(e, true) 679 } 680 } 681 } 682 683 // update loops until the lifetime of the whisper node, updating its internal 684 // state by expiring stale messages from the pool. 685 func (w *Whisper) update() { 686 // Start a ticker to check for expirations 687 expire := time.NewTicker(expirationCycle) 688 689 // Repeat updates until termination is requested 690 for { 691 select { 692 case <-expire.C: 693 w.expire() 694 695 case <-w.quit: 696 return 697 } 698 } 699 } 700 701 // expire iterates over all the expiration timestamps, removing all stale 702 // messages from the pools. 703 func (w *Whisper) expire() { 704 w.poolMu.Lock() 705 defer w.poolMu.Unlock() 706 707 w.statsMu.Lock() 708 defer w.statsMu.Unlock() 709 w.stats.reset() 710 now := uint32(time.Now().Unix()) 711 for expiry, hashSet := range w.expirations { 712 if expiry < now { 713 // Dump all expired messages and remove timestamp 714 hashSet.Each(func(v interface{}) bool { 715 sz := w.envelopes[v.(common.Hash)].size() 716 delete(w.envelopes, v.(common.Hash)) 717 w.stats.messagesCleared++ 718 w.stats.memoryCleared += sz 719 w.stats.memoryUsed -= sz 720 return true 721 }) 722 w.expirations[expiry].Clear() 723 delete(w.expirations, expiry) 724 } 725 } 726 } 727 728 // Stats returns the whisper node statistics. 729 func (w *Whisper) Stats() Statistics { 730 w.statsMu.Lock() 731 defer w.statsMu.Unlock() 732 733 return w.stats 734 } 735 736 // Envelopes retrieves all the messages currently pooled by the node. 737 func (w *Whisper) Envelopes() []*Envelope { 738 w.poolMu.RLock() 739 defer w.poolMu.RUnlock() 740 741 all := make([]*Envelope, 0, len(w.envelopes)) 742 for _, envelope := range w.envelopes { 743 all = append(all, envelope) 744 } 745 return all 746 } 747 748 // Messages iterates through all currently floating envelopes 749 // and retrieves all the messages, that this filter could decrypt. 750 func (w *Whisper) Messages(id string) []*ReceivedMessage { 751 result := make([]*ReceivedMessage, 0) 752 w.poolMu.RLock() 753 defer w.poolMu.RUnlock() 754 755 if filter := w.filters.Get(id); filter != nil { 756 for _, env := range w.envelopes { 757 msg := filter.processEnvelope(env) 758 if msg != nil { 759 result = append(result, msg) 760 } 761 } 762 } 763 return result 764 } 765 766 // isEnvelopeCached checks if envelope with specific hash has already been received and cached. 767 func (w *Whisper) isEnvelopeCached(hash common.Hash) bool { 768 w.poolMu.Lock() 769 defer w.poolMu.Unlock() 770 771 _, exist := w.envelopes[hash] 772 return exist 773 } 774 775 // reset resets the node's statistics after each expiry cycle. 776 func (s *Statistics) reset() { 777 s.cycles++ 778 s.totalMessagesCleared += s.messagesCleared 779 780 s.memoryCleared = 0 781 s.messagesCleared = 0 782 } 783 784 // ValidatePublicKey checks the format of the given public key. 785 func ValidatePublicKey(k *ecdsa.PublicKey) bool { 786 return k != nil && k.X != nil && k.Y != nil && k.X.Sign() != 0 && k.Y.Sign() != 0 787 } 788 789 // validatePrivateKey checks the format of the given private key. 790 func validatePrivateKey(k *ecdsa.PrivateKey) bool { 791 if k == nil || k.D == nil || k.D.Sign() == 0 { 792 return false 793 } 794 return ValidatePublicKey(&k.PublicKey) 795 } 796 797 // validateSymmetricKey returns false if the key contains all zeros 798 func validateSymmetricKey(k []byte) bool { 799 return len(k) > 0 && !containsOnlyZeros(k) 800 } 801 802 // containsOnlyZeros checks if the data contain only zeros. 803 func containsOnlyZeros(data []byte) bool { 804 for _, b := range data { 805 if b != 0 { 806 return false 807 } 808 } 809 return true 810 } 811 812 // bytesToUintLittleEndian converts the slice to 64-bit unsigned integer. 813 func bytesToUintLittleEndian(b []byte) (res uint64) { 814 mul := uint64(1) 815 for i := 0; i < len(b); i++ { 816 res += uint64(b[i]) * mul 817 mul *= 256 818 } 819 return res 820 } 821 822 // BytesToUintBigEndian converts the slice to 64-bit unsigned integer. 823 func BytesToUintBigEndian(b []byte) (res uint64) { 824 for i := 0; i < len(b); i++ { 825 res *= 256 826 res += uint64(b[i]) 827 } 828 return res 829 } 830 831 // deriveKeyMaterial derives symmetric key material from the key or password. 832 // pbkdf2 is used for security, in case people use password instead of randomly generated keys. 833 func deriveKeyMaterial(key []byte, version uint64) (derivedKey []byte, err error) { 834 if version == 0 { 835 // kdf should run no less than 0.1 seconds on average compute, 836 // because it's a once in a session experience 837 derivedKey := pbkdf2.Key(key, nil, 65356, aesKeyLength, sha256.New) 838 return derivedKey, nil 839 } 840 return nil, unknownVersionError(version) 841 } 842 843 // GenerateRandomID generates a random string, which is then returned to be used as a key id 844 func GenerateRandomID() (id string, err error) { 845 buf := make([]byte, keyIdSize) 846 _, err = crand.Read(buf) 847 if err != nil { 848 return "", err 849 } 850 if !validateSymmetricKey(buf) { 851 return "", fmt.Errorf("error in generateRandomID: crypto/rand failed to generate random data") 852 } 853 id = common.Bytes2Hex(buf) 854 return id, err 855 }