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  }