github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/xeth/whisper.go (about) 1 // Copyright 2015 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 // Contains the external API to the whisper sub-protocol. 18 19 package xeth 20 21 import ( 22 "fmt" 23 "time" 24 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/crypto" 27 "github.com/ethereum/go-ethereum/logger" 28 "github.com/ethereum/go-ethereum/whisper" 29 ) 30 31 var qlogger = logger.NewLogger("XSHH") 32 33 // Whisper represents the API wrapper around the internal whisper implementation. 34 type Whisper struct { 35 *whisper.Whisper 36 } 37 38 // NewWhisper wraps an internal whisper client into an external API version. 39 func NewWhisper(w *whisper.Whisper) *Whisper { 40 return &Whisper{w} 41 } 42 43 // NewIdentity generates a new cryptographic identity for the client, and injects 44 // it into the known identities for message decryption. 45 func (self *Whisper) NewIdentity() string { 46 identity := self.Whisper.NewIdentity() 47 return common.ToHex(crypto.FromECDSAPub(&identity.PublicKey)) 48 } 49 50 // HasIdentity checks if the the whisper node is configured with the private key 51 // of the specified public pair. 52 func (self *Whisper) HasIdentity(key string) bool { 53 return self.Whisper.HasIdentity(crypto.ToECDSAPub(common.FromHex(key))) 54 } 55 56 // Post injects a message into the whisper network for distribution. 57 func (self *Whisper) Post(payload string, to, from string, topics []string, priority, ttl uint32) error { 58 // Decode the topic strings 59 topicsDecoded := make([][]byte, len(topics)) 60 for i, topic := range topics { 61 topicsDecoded[i] = common.FromHex(topic) 62 } 63 // Construct the whisper message and transmission options 64 message := whisper.NewMessage(common.FromHex(payload)) 65 options := whisper.Options{ 66 To: crypto.ToECDSAPub(common.FromHex(to)), 67 TTL: time.Duration(ttl) * time.Second, 68 Topics: whisper.NewTopics(topicsDecoded...), 69 } 70 if len(from) != 0 { 71 if key := self.Whisper.GetIdentity(crypto.ToECDSAPub(common.FromHex(from))); key != nil { 72 options.From = key 73 } else { 74 return fmt.Errorf("unknown identity to send from: %s", from) 75 } 76 } 77 // Wrap and send the message 78 pow := time.Duration(priority) * time.Millisecond 79 envelope, err := message.Wrap(pow, options) 80 if err != nil { 81 return err 82 } 83 if err := self.Whisper.Send(envelope); err != nil { 84 return err 85 } 86 return nil 87 } 88 89 // Watch installs a new message handler to run in case a matching packet arrives 90 // from the whisper network. 91 func (self *Whisper) Watch(to, from string, topics [][]string, fn func(WhisperMessage)) int { 92 // Decode the topic strings 93 topicsDecoded := make([][][]byte, len(topics)) 94 for i, condition := range topics { 95 topicsDecoded[i] = make([][]byte, len(condition)) 96 for j, topic := range condition { 97 topicsDecoded[i][j] = common.FromHex(topic) 98 } 99 } 100 // Assemble and inject the filter into the whisper client 101 filter := whisper.Filter{ 102 To: crypto.ToECDSAPub(common.FromHex(to)), 103 From: crypto.ToECDSAPub(common.FromHex(from)), 104 Topics: whisper.NewFilterTopics(topicsDecoded...), 105 } 106 filter.Fn = func(message *whisper.Message) { 107 fn(NewWhisperMessage(message)) 108 } 109 return self.Whisper.Watch(filter) 110 } 111 112 // Messages retrieves all the currently pooled messages matching a filter id. 113 func (self *Whisper) Messages(id int) []WhisperMessage { 114 pool := self.Whisper.Messages(id) 115 116 messages := make([]WhisperMessage, len(pool)) 117 for i, message := range pool { 118 messages[i] = NewWhisperMessage(message) 119 } 120 return messages 121 }