diff options
Diffstat (limited to 'whisper')
-rw-r--r-- | whisper/envelope.go | 42 | ||||
-rw-r--r-- | whisper/filter.go | 2 | ||||
-rw-r--r-- | whisper/main.go | 2 | ||||
-rw-r--r-- | whisper/message.go | 11 | ||||
-rw-r--r-- | whisper/peer.go | 4 | ||||
-rw-r--r-- | whisper/whisper.go | 78 | ||||
-rw-r--r-- | whisper/whisper_test.go | 11 |
7 files changed, 93 insertions, 57 deletions
diff --git a/whisper/envelope.go b/whisper/envelope.go index 9d28dfa6b..3c477ad9f 100644 --- a/whisper/envelope.go +++ b/whisper/envelope.go @@ -1,11 +1,9 @@ package whisper import ( - "bytes" "crypto/ecdsa" "encoding/binary" "fmt" - "io" "time" "github.com/ethereum/go-ethereum/crypto" @@ -28,22 +26,6 @@ type Envelope struct { hash Hash } -func NewEnvelopeFromReader(reader io.Reader) (*Envelope, error) { - var envelope Envelope - - buf := new(bytes.Buffer) - buf.ReadFrom(reader) - - h := H(crypto.Sha3(buf.Bytes())) - if err := rlp.Decode(buf, &envelope); err != nil { - return nil, err - } - - envelope.hash = h - - return &envelope, nil -} - func (self *Envelope) Hash() Hash { if self.hash == EmptyHash { self.hash = H(crypto.Sha3(ethutil.Encode(self))) @@ -126,3 +108,27 @@ func (self *Envelope) withoutNonce() interface{} { func (self *Envelope) RlpData() interface{} { return []interface{}{self.Expiry, self.Ttl, ethutil.ByteSliceToInterface(self.Topics), self.Data, self.Nonce} } + +func (self *Envelope) DecodeRLP(s *rlp.Stream) error { + var extenv struct { + Expiry uint32 + Ttl uint32 + Topics [][]byte + Data []byte + Nonce uint32 + } + if err := s.Decode(&extenv); err != nil { + return err + } + + self.Expiry = extenv.Expiry + self.Ttl = extenv.Ttl + self.Topics = extenv.Topics + self.Data = extenv.Data + self.Nonce = extenv.Nonce + + // TODO We should use the stream directly here. + self.hash = H(crypto.Sha3(ethutil.Encode(self))) + + return nil +} diff --git a/whisper/filter.go b/whisper/filter.go index 4315aa556..b33f2c1a2 100644 --- a/whisper/filter.go +++ b/whisper/filter.go @@ -3,7 +3,7 @@ package whisper import "crypto/ecdsa" type Filter struct { - To *ecdsa.PrivateKey + To *ecdsa.PublicKey From *ecdsa.PublicKey Topics [][]byte Fn func(*Message) diff --git a/whisper/main.go b/whisper/main.go index edd5f7004..9f35dbb8d 100644 --- a/whisper/main.go +++ b/whisper/main.go @@ -7,10 +7,10 @@ import ( "log" "os" + "github.com/ethereum/go-ethereum/crypto/secp256k1" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/whisper" - "github.com/obscuren/secp256k1-go" ) func main() { diff --git a/whisper/message.go b/whisper/message.go index db0110b4a..5d9e5b5c1 100644 --- a/whisper/message.go +++ b/whisper/message.go @@ -11,10 +11,13 @@ type Message struct { Flags byte Signature []byte Payload []byte + Sent int64 + + To *ecdsa.PublicKey } func NewMessage(payload []byte) *Message { - return &Message{Flags: 0, Payload: payload} + return &Message{Flags: 0, Payload: payload, Sent: time.Now().Unix()} } func (self *Message) hash() []byte { @@ -67,7 +70,11 @@ func (self *Message) Seal(pow time.Duration, opts Opts) (*Envelope, error) { } } - envelope := NewEnvelope(DefaultTtl, opts.Topics, self) + if opts.Ttl == 0 { + opts.Ttl = DefaultTtl + } + + envelope := NewEnvelope(opts.Ttl, opts.Topics, self) envelope.Seal(pow) return envelope, nil diff --git a/whisper/peer.go b/whisper/peer.go index d42b374b5..332ddd22a 100644 --- a/whisper/peer.go +++ b/whisper/peer.go @@ -55,7 +55,7 @@ out: case <-relay.C: err := self.broadcast(self.host.envelopes()) if err != nil { - self.peer.Infoln(err) + self.peer.Infoln("broadcast err:", err) break out } @@ -81,7 +81,7 @@ func (self *peer) broadcast(envelopes []*Envelope) error { if err := self.ws.WriteMsg(msg); err != nil { return err } - self.peer.Infoln("broadcasted", i, "message(s)") + self.peer.DebugDetailln("broadcasted", i, "message(s)") } return nil diff --git a/whisper/whisper.go b/whisper/whisper.go index ffcdd7d40..066f2c4ea 100644 --- a/whisper/whisper.go +++ b/whisper/whisper.go @@ -60,7 +60,7 @@ type Whisper struct { quit chan struct{} - keys []*ecdsa.PrivateKey + keys map[string]*ecdsa.PrivateKey } func New() *Whisper { @@ -69,6 +69,7 @@ func New() *Whisper { filters: filter.New(), expiry: make(map[uint32]*set.SetNonTS), quit: make(chan struct{}), + keys: make(map[string]*ecdsa.PrivateKey), } whisper.filters.Start() @@ -101,23 +102,23 @@ func (self *Whisper) NewIdentity() *ecdsa.PrivateKey { if err != nil { panic(err) } - self.keys = append(self.keys, key) + + self.keys[string(crypto.FromECDSAPub(&key.PublicKey))] = key return key } -func (self *Whisper) HasIdentity(key *ecdsa.PrivateKey) bool { - for _, key := range self.keys { - if key.D.Cmp(key.D) == 0 { - return true - } - } - return false +func (self *Whisper) HasIdentity(key *ecdsa.PublicKey) bool { + return self.keys[string(crypto.FromECDSAPub(key))] != nil +} + +func (self *Whisper) GetIdentity(key *ecdsa.PublicKey) *ecdsa.PrivateKey { + return self.keys[string(crypto.FromECDSAPub(key))] } func (self *Whisper) Watch(opts Filter) int { return self.filters.Install(filter.Generic{ - Str1: string(crypto.FromECDSA(opts.To)), + Str1: string(crypto.FromECDSAPub(opts.To)), Str2: string(crypto.FromECDSAPub(opts.From)), Data: bytesToMap(opts.Topics), Fn: func(data interface{}) { @@ -126,6 +127,22 @@ func (self *Whisper) Watch(opts Filter) int { }) } +func (self *Whisper) Messages(id int) (messages []*Message) { + filter := self.filters.Get(id) + if filter != nil { + for _, e := range self.messages { + if msg, key := self.open(e); msg != nil { + f := createFilter(msg, e.Topics, key) + if self.filters.Match(filter, f) { + messages = append(messages, msg) + } + } + } + } + + return +} + // Main handler for passing whisper messages to whisper peer objects func (self *Whisper) msgHandler(peer *p2p.Peer, ws p2p.MsgReadWriter) error { wpeer := NewPeer(self, peer, ws) @@ -144,17 +161,19 @@ func (self *Whisper) msgHandler(peer *p2p.Peer, ws p2p.MsgReadWriter) error { return err } - envelope, err := NewEnvelopeFromReader(msg.Payload) - if err != nil { + var envelopes []*Envelope + if err := msg.Decode(&envelopes); err != nil { peer.Infoln(err) continue } - if err := self.add(envelope); err != nil { - // TODO Punish peer here. Invalid envelope. - peer.Infoln(err) + for _, envelope := range envelopes { + if err := self.add(envelope); err != nil { + // TODO Punish peer here. Invalid envelope. + peer.Infoln(err) + } + wpeer.addKnown(envelope) } - wpeer.addKnown(envelope) } } @@ -178,6 +197,8 @@ func (self *Whisper) add(envelope *Envelope) error { go self.postEvent(envelope) } + wlogger.DebugDetailf("added whisper envelope %x\n", envelope) + return nil } @@ -227,19 +248,30 @@ func (self *Whisper) envelopes() (envelopes []*Envelope) { } func (self *Whisper) postEvent(envelope *Envelope) { + if message, key := self.open(envelope); message != nil { + self.filters.Notify(createFilter(message, envelope.Topics, key), message) + } +} + +func (self *Whisper) open(envelope *Envelope) (*Message, *ecdsa.PrivateKey) { for _, key := range self.keys { if message, err := envelope.Open(key); err == nil || (err != nil && err == ecies.ErrInvalidPublicKey) { - // Create a custom filter? - self.filters.Notify(filter.Generic{ - Str1: string(crypto.FromECDSA(key)), Str2: string(crypto.FromECDSAPub(message.Recover())), - Data: bytesToMap(envelope.Topics), - }, message) - } else { - wlogger.Infoln(err) + message.To = &key.PublicKey + + return message, key } } + + return nil, nil } func (self *Whisper) Protocol() p2p.Protocol { return self.protocol } + +func createFilter(message *Message, topics [][]byte, key *ecdsa.PrivateKey) filter.Filter { + return filter.Generic{ + Str1: string(crypto.FromECDSAPub(&key.PublicKey)), Str2: string(crypto.FromECDSAPub(message.Recover())), + Data: bytesToMap(topics), + } +} diff --git a/whisper/whisper_test.go b/whisper/whisper_test.go index 107cb8c97..3e3945a0a 100644 --- a/whisper/whisper_test.go +++ b/whisper/whisper_test.go @@ -6,21 +6,12 @@ import ( "time" ) -func TestKeyManagement(t *testing.T) { - whisper := New() - - key := whisper.NewIdentity() - if !whisper.HasIdentity(key) { - t.Error("expected whisper to have identify") - } -} - func TestEvent(t *testing.T) { res := make(chan *Message, 1) whisper := New() id := whisper.NewIdentity() whisper.Watch(Filter{ - To: id, + To: &id.PublicKey, Fn: func(msg *Message) { res <- msg }, |