github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/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 "crypto/ecdsa" 21 crand "crypto/rand" 22 "crypto/sha256" 23 "fmt" 24 "runtime" 25 "sync" 26 "time" 27 28 libp2p "github.com/libp2p/go-libp2p-peer" 29 "github.com/syndtr/goleveldb/leveldb/errors" 30 "github.com/vntchain/go-vnt/common" 31 "github.com/vntchain/go-vnt/crypto" 32 "github.com/vntchain/go-vnt/log" 33 "github.com/vntchain/go-vnt/rpc" 34 "github.com/vntchain/go-vnt/vntp2p" 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 VNT 55 // network, using its very own P2P communication layer. 56 type Whisper struct { 57 protocol vntp2p.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 VNT 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 = vntp2p.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() []vntp2p.Protocol { 161 return []vntp2p.Protocol{w.protocol} 162 } 163 164 // Version returns the whisper sub-protocols version number. 165 func (w *Whisper) Version() uint { 166 //return uint(1) 167 return w.protocol.Version 168 } 169 170 // SetMaxMessageSize sets the maximal message size allowed by this node 171 func (w *Whisper) SetMaxMessageSize(size uint32) error { 172 if size > MaxMessageSize { 173 return fmt.Errorf("message size too large [%d>%d]", size, MaxMessageSize) 174 } 175 w.settings.Store(maxMsgSizeIdx, size) 176 return nil 177 } 178 179 // SetMinimumPoW sets the minimal PoW required by this node 180 func (w *Whisper) SetMinimumPoW(val float64) error { 181 if val <= 0.0 { 182 return fmt.Errorf("invalid PoW: %f", val) 183 } 184 w.settings.Store(minPowIdx, val) 185 return nil 186 } 187 188 // getPeer retrieves peer by ID 189 func (w *Whisper) getPeer(peerID libp2p.ID) (*Peer, error) { 190 w.peerMu.Lock() 191 defer w.peerMu.Unlock() 192 for p := range w.peers { 193 id := p.peer.RemoteID() 194 if peerID == id { 195 return p, nil 196 } 197 } 198 return nil, fmt.Errorf("Could not find peer with ID: %x", peerID) 199 } 200 201 // AllowP2PMessagesFromPeer marks specific peer trusted, 202 // which will allow it to send historic (expired) messages. 203 func (w *Whisper) AllowP2PMessagesFromPeer(peerID libp2p.ID) error { 204 p, err := w.getPeer(peerID) 205 if err != nil { 206 return err 207 } 208 p.trusted = true 209 return nil 210 } 211 212 // RequestHistoricMessages sends a message with p2pRequestCode to a specific peer, 213 // which is known to implement MailServer interface, and is supposed to process this 214 // request and respond with a number of peer-to-peer messages (possibly expired), 215 // which are not supposed to be forwarded any further. 216 // The whisper protocol is agnostic of the format and contents of envelope. 217 func (w *Whisper) RequestHistoricMessages(peerID libp2p.ID, envelope *Envelope) error { 218 p, err := w.getPeer(peerID) 219 if err != nil { 220 return err 221 } 222 p.trusted = true 223 return vntp2p.Send(p.ws, ProtocolName, p2pRequestCode, envelope) 224 } 225 226 // SendP2PMessage sends a peer-to-peer message to a specific peer. 227 func (w *Whisper) SendP2PMessage(peerID libp2p.ID, envelope *Envelope) error { 228 p, err := w.getPeer(peerID) 229 if err != nil { 230 return err 231 } 232 return w.SendP2PDirect(p, envelope) 233 } 234 235 // SendP2PDirect sends a peer-to-peer message to a specific peer. 236 func (w *Whisper) SendP2PDirect(peer *Peer, envelope *Envelope) error { 237 return vntp2p.Send(peer.ws, ProtocolName, p2pCode, envelope) 238 } 239 240 // NewKeyPair generates a new cryptographic identity for the client, and injects 241 // it into the known identities for message decryption. Returns ID of the new key pair. 242 func (w *Whisper) NewKeyPair() (string, error) { 243 key, err := crypto.GenerateKey() 244 if err != nil || !validatePrivateKey(key) { 245 key, err = crypto.GenerateKey() // retry once 246 } 247 if err != nil { 248 return "", err 249 } 250 if !validatePrivateKey(key) { 251 return "", fmt.Errorf("failed to generate valid key") 252 } 253 254 id, err := GenerateRandomID() 255 if err != nil { 256 return "", fmt.Errorf("failed to generate ID: %s", err) 257 } 258 259 w.keyMu.Lock() 260 defer w.keyMu.Unlock() 261 262 if w.privateKeys[id] != nil { 263 return "", fmt.Errorf("failed to generate unique ID") 264 } 265 w.privateKeys[id] = key 266 return id, nil 267 } 268 269 // DeleteKeyPair deletes the specified key if it exists. 270 func (w *Whisper) DeleteKeyPair(key string) bool { 271 w.keyMu.Lock() 272 defer w.keyMu.Unlock() 273 274 if w.privateKeys[key] != nil { 275 delete(w.privateKeys, key) 276 return true 277 } 278 return false 279 } 280 281 // AddKeyPair imports a asymmetric private key and returns it identifier. 282 func (w *Whisper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) { 283 id, err := GenerateRandomID() 284 if err != nil { 285 return "", fmt.Errorf("failed to generate ID: %s", err) 286 } 287 288 w.keyMu.Lock() 289 w.privateKeys[id] = key 290 w.keyMu.Unlock() 291 292 return id, nil 293 } 294 295 // HasKeyPair checks if the the whisper node is configured with the private key 296 // of the specified public pair. 297 func (w *Whisper) HasKeyPair(id string) bool { 298 w.keyMu.RLock() 299 defer w.keyMu.RUnlock() 300 return w.privateKeys[id] != nil 301 } 302 303 // GetPrivateKey retrieves the private key of the specified identity. 304 func (w *Whisper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) { 305 w.keyMu.RLock() 306 defer w.keyMu.RUnlock() 307 key := w.privateKeys[id] 308 if key == nil { 309 return nil, fmt.Errorf("invalid id") 310 } 311 return key, nil 312 } 313 314 // GenerateSymKey generates a random symmetric key and stores it under id, 315 // which is then returned. Will be used in the future for session key exchange. 316 func (w *Whisper) GenerateSymKey() (string, error) { 317 key := make([]byte, aesKeyLength) 318 _, err := crand.Read(key) 319 if err != nil { 320 return "", err 321 } else if !validateSymmetricKey(key) { 322 return "", fmt.Errorf("error in GenerateSymKey: crypto/rand failed to generate random data") 323 } 324 325 id, err := GenerateRandomID() 326 if err != nil { 327 return "", fmt.Errorf("failed to generate ID: %s", err) 328 } 329 330 w.keyMu.Lock() 331 defer w.keyMu.Unlock() 332 333 if w.symKeys[id] != nil { 334 return "", fmt.Errorf("failed to generate unique ID") 335 } 336 w.symKeys[id] = key 337 return id, nil 338 } 339 340 // AddSymKeyDirect stores the key, and returns its id. 341 func (w *Whisper) AddSymKeyDirect(key []byte) (string, error) { 342 if len(key) != aesKeyLength { 343 return "", fmt.Errorf("wrong key size: %d", len(key)) 344 } 345 346 id, err := GenerateRandomID() 347 if err != nil { 348 return "", fmt.Errorf("failed to generate ID: %s", err) 349 } 350 351 w.keyMu.Lock() 352 defer w.keyMu.Unlock() 353 354 if w.symKeys[id] != nil { 355 return "", fmt.Errorf("failed to generate unique ID") 356 } 357 w.symKeys[id] = key 358 return id, nil 359 } 360 361 // AddSymKeyFromPassword generates the key from password, stores it, and returns its id. 362 func (w *Whisper) AddSymKeyFromPassword(password string) (string, error) { 363 id, err := GenerateRandomID() 364 if err != nil { 365 return "", fmt.Errorf("failed to generate ID: %s", err) 366 } 367 if w.HasSymKey(id) { 368 return "", fmt.Errorf("failed to generate unique ID") 369 } 370 371 derived, err := deriveKeyMaterial([]byte(password), EnvelopeVersion) 372 if err != nil { 373 return "", err 374 } 375 376 w.keyMu.Lock() 377 defer w.keyMu.Unlock() 378 379 // double check is necessary, because deriveKeyMaterial() is very slow 380 if w.symKeys[id] != nil { 381 return "", fmt.Errorf("critical error: failed to generate unique ID") 382 } 383 w.symKeys[id] = derived 384 return id, nil 385 } 386 387 // HasSymKey returns true if there is a key associated with the given id. 388 // Otherwise returns false. 389 func (w *Whisper) HasSymKey(id string) bool { 390 w.keyMu.RLock() 391 defer w.keyMu.RUnlock() 392 return w.symKeys[id] != nil 393 } 394 395 // DeleteSymKey deletes the key associated with the name string if it exists. 396 func (w *Whisper) DeleteSymKey(id string) bool { 397 w.keyMu.Lock() 398 defer w.keyMu.Unlock() 399 if w.symKeys[id] != nil { 400 delete(w.symKeys, id) 401 return true 402 } 403 return false 404 } 405 406 // GetSymKey returns the symmetric key associated with the given id. 407 func (w *Whisper) GetSymKey(id string) ([]byte, error) { 408 w.keyMu.RLock() 409 defer w.keyMu.RUnlock() 410 if w.symKeys[id] != nil { 411 return w.symKeys[id], nil 412 } 413 return nil, fmt.Errorf("non-existent key ID") 414 } 415 416 // Subscribe installs a new message handler used for filtering, decrypting 417 // and subsequent storing of incoming messages. 418 func (w *Whisper) Subscribe(f *Filter) (string, error) { 419 return w.filters.Install(f) 420 } 421 422 // GetFilter returns the filter by id. 423 func (w *Whisper) GetFilter(id string) *Filter { 424 return w.filters.Get(id) 425 } 426 427 // Unsubscribe removes an installed message handler. 428 func (w *Whisper) Unsubscribe(id string) error { 429 ok := w.filters.Uninstall(id) 430 if !ok { 431 return fmt.Errorf("Unsubscribe: Invalid ID") 432 } 433 return nil 434 } 435 436 // Send injects a message into the whisper send queue, to be distributed in the 437 // network in the coming cycles. 438 func (w *Whisper) Send(envelope *Envelope) error { 439 ok, err := w.add(envelope) 440 if err != nil { 441 return err 442 } 443 if !ok { 444 return fmt.Errorf("failed to add envelope") 445 } 446 return err 447 } 448 449 // Start implements node.Service, starting the background data propagation thread 450 // of the Whisper protocol. 451 func (w *Whisper) Start(*vntp2p.Server) error { 452 log.Info("started whisper v." + ProtocolVersionStr) 453 go w.update() 454 455 numCPU := runtime.NumCPU() 456 for i := 0; i < numCPU; i++ { 457 go w.processQueue() 458 } 459 460 return nil 461 } 462 463 // Stop implements node.Service, stopping the background data propagation thread 464 // of the Whisper protocol. 465 func (w *Whisper) Stop() error { 466 close(w.quit) 467 log.Info("whisper stopped") 468 return nil 469 } 470 471 // HandlePeer is called by the underlying P2P layer when the whisper sub-protocol 472 // connection is negotiated. 473 func (w *Whisper) HandlePeer(peer *vntp2p.Peer, rw vntp2p.MsgReadWriter) error { 474 // Create the new peer and start tracking it 475 whisperPeer := newPeer(w, peer, rw) 476 477 w.peerMu.Lock() 478 w.peers[whisperPeer] = struct{}{} 479 w.peerMu.Unlock() 480 481 defer func() { 482 w.peerMu.Lock() 483 delete(w.peers, whisperPeer) 484 w.peerMu.Unlock() 485 }() 486 487 // Run the peer handshake and state updates 488 if err := whisperPeer.handshake(); err != nil { 489 return err 490 } 491 whisperPeer.start() 492 defer whisperPeer.stop() 493 494 return w.runMessageLoop(whisperPeer, rw) 495 } 496 497 // runMessageLoop reads and processes inbound messages directly to merge into client-global state. 498 func (w *Whisper) runMessageLoop(p *Peer, rw vntp2p.MsgReadWriter) error { 499 for { 500 // fetch the next packet 501 packet, err := rw.ReadMsg() 502 if err != nil { 503 log.Warn("message loop", "peer", p.peer.RemoteID(), "err", err) 504 return err 505 } 506 if packet.GetBodySize() > w.MaxMessageSize() { 507 log.Warn("oversized message received", "peer", p.peer.RemoteID()) 508 return errors.New("oversized message received") 509 } 510 511 switch packet.Body.Type { 512 case statusCode: 513 // this should not happen, but no need to panic; just ignore this message. 514 log.Warn("unxepected status message received", "peer", p.peer.RemoteID()) 515 case messagesCode: 516 // decode the contained envelopes 517 var envelope Envelope 518 if err := packet.Decode(&envelope); err != nil { 519 log.Warn("failed to decode envelope, peer will be disconnected", "peer", p.peer.RemoteID(), "err", err) 520 return errors.New("invalid envelope") 521 } 522 cached, err := w.add(&envelope) 523 if err != nil { 524 log.Warn("bad envelope received, peer will be disconnected", "peer", p.peer.RemoteID(), "err", err) 525 return errors.New("invalid envelope") 526 } 527 if cached { 528 p.mark(&envelope) 529 } 530 case p2pCode: 531 // peer-to-peer message, sent directly to peer bypassing PoW checks, etc. 532 // this message is not supposed to be forwarded to other peers, and 533 // therefore might not satisfy the PoW, expiry and other requirements. 534 // these messages are only accepted from the trusted peer. 535 if p.trusted { 536 var envelope Envelope 537 if err := packet.Decode(&envelope); err != nil { 538 log.Warn("failed to decode direct message, peer will be disconnected", "peer", p.peer.RemoteID(), "err", err) 539 return errors.New("invalid direct message") 540 } 541 w.postEvent(&envelope, true) 542 } 543 case p2pRequestCode: 544 // Must be processed if mail server is implemented. Otherwise ignore. 545 if w.mailServer != nil { 546 var request Envelope 547 if err := packet.Decode(&request); err != nil { 548 log.Warn("failed to decode p2p request message, peer will be disconnected", "peer", p.peer.RemoteID(), "err", err) 549 return errors.New("invalid p2p request") 550 } 551 w.mailServer.DeliverMail(p, &request) 552 } 553 default: 554 // New message types might be implemented in the future versions of Whisper. 555 // For forward compatibility, just ignore. 556 } 557 558 // -- 按理说,新版的协议处理方式,不会有残留数据得不到处理 559 //packet.Discard() 560 } 561 } 562 563 // add inserts a new envelope into the message pool to be distributed within the 564 // whisper network. It also inserts the envelope into the expiration pool at the 565 // appropriate time-stamp. In case of error, connection should be dropped. 566 func (w *Whisper) add(envelope *Envelope) (bool, error) { 567 now := uint32(time.Now().Unix()) 568 sent := envelope.Expiry - envelope.TTL 569 570 if sent > now { 571 if sent-SynchAllowance > now { 572 return false, fmt.Errorf("envelope created in the future [%x]", envelope.Hash()) 573 } 574 // recalculate PoW, adjusted for the time difference, plus one second for latency 575 envelope.calculatePoW(sent - now + 1) 576 } 577 578 if envelope.Expiry < now { 579 if envelope.Expiry+SynchAllowance*2 < now { 580 return false, fmt.Errorf("very old message") 581 } 582 log.Debug("expired envelope dropped", "hash", envelope.Hash().Hex()) 583 return false, nil // drop envelope without error 584 } 585 586 if uint32(envelope.size()) > w.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() < w.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 w.poolMu.Lock() 609 _, alreadyCached := w.envelopes[hash] 610 if !alreadyCached { 611 w.envelopes[hash] = envelope 612 if w.expirations[envelope.Expiry] == nil { 613 w.expirations[envelope.Expiry] = set.NewNonTS() 614 } 615 if !w.expirations[envelope.Expiry].Has(hash) { 616 w.expirations[envelope.Expiry].Add(hash) 617 } 618 } 619 w.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 w.statsMu.Lock() 626 w.stats.memoryUsed += envelope.size() 627 w.statsMu.Unlock() 628 w.postEvent(envelope, false) // notify the local node about the new message 629 if w.mailServer != nil { 630 w.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 } 842 return nil, unknownVersionError(version) 843 } 844 845 // GenerateRandomID generates a random string, which is then returned to be used as a key id 846 func GenerateRandomID() (id string, err error) { 847 buf := make([]byte, keyIdSize) 848 _, err = crand.Read(buf) 849 if err != nil { 850 return "", err 851 } 852 if !validateSymmetricKey(buf) { 853 return "", fmt.Errorf("error in generateRandomID: crypto/rand failed to generate random data") 854 } 855 id = common.Bytes2Hex(buf) 856 return id, err 857 }