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