From ebe2d9d872c5482e02508f1d3e9c3a56e8a41d44 Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 8 Dec 2014 12:43:33 +0100 Subject: First draft of Whisper messages relaying --- whisper/envelope.go | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 whisper/envelope.go (limited to 'whisper/envelope.go') diff --git a/whisper/envelope.go b/whisper/envelope.go new file mode 100644 index 000000000..f9254843c --- /dev/null +++ b/whisper/envelope.go @@ -0,0 +1,96 @@ +package whisper + +import ( + "bytes" + "encoding/binary" + "io" + "time" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/rlp" +) + +const ( + DefaultTtl = 50 * time.Second +) + +type Envelope struct { + Expiry int32 // Whisper protocol specifies int32, really should be int64 + Ttl int32 // ^^^^^^ + Topics [][]byte + Data []byte + Nonce uint32 + + 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))) + } + + return self.hash +} + +func NewEnvelope(ttl time.Duration, topics [][]byte, data *Message) *Envelope { + exp := time.Now().Add(ttl) + + return &Envelope{int32(exp.Unix()), int32(ttl.Seconds()), topics, data.Bytes(), 0, Hash{}} +} + +func (self *Envelope) Seal() { + self.proveWork(DefaultTtl) +} + +func (self *Envelope) proveWork(dura time.Duration) { + var bestBit int + d := make([]byte, 64) + copy(d[:32], ethutil.Encode(self.withoutNonce())) + + then := time.Now().Add(dura).UnixNano() + for n := uint32(0); time.Now().UnixNano() < then; { + for i := 0; i < 1024; i++ { + binary.BigEndian.PutUint32(d[60:], n) + + fbs := ethutil.FirstBitSet(ethutil.BigD(crypto.Sha3(d))) + if fbs > bestBit { + bestBit = fbs + self.Nonce = n + } + + n++ + } + } +} + +func (self *Envelope) valid() bool { + d := make([]byte, 64) + copy(d[:32], ethutil.Encode(self.withoutNonce())) + binary.BigEndian.PutUint32(d[60:], self.Nonce) + return ethutil.FirstBitSet(ethutil.BigD(crypto.Sha3(d))) > 0 +} + +func (self *Envelope) withoutNonce() interface{} { + return []interface{}{self.Expiry, self.Ttl, ethutil.ByteSliceToInterface(self.Topics), self.Data} +} + +func (self *Envelope) RlpData() interface{} { + return []interface{}{self.Expiry, self.Ttl, ethutil.ByteSliceToInterface(self.Topics), self.Data, self.Nonce} +} -- cgit From 76842b0df8b5605682362bd57fbd6eb315bcaf1f Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 8 Dec 2014 14:25:52 +0100 Subject: Additional checks and debug output --- whisper/envelope.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'whisper/envelope.go') diff --git a/whisper/envelope.go b/whisper/envelope.go index f9254843c..8e66a7bbb 100644 --- a/whisper/envelope.go +++ b/whisper/envelope.go @@ -12,7 +12,7 @@ import ( ) const ( - DefaultTtl = 50 * time.Second + DefaultPow = 50 * time.Millisecond ) type Envelope struct { @@ -56,7 +56,7 @@ func NewEnvelope(ttl time.Duration, topics [][]byte, data *Message) *Envelope { } func (self *Envelope) Seal() { - self.proveWork(DefaultTtl) + self.proveWork(DefaultPow) } func (self *Envelope) proveWork(dura time.Duration) { -- cgit From 984c7e6689f720e0b60a462e00793364de397909 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 10 Dec 2014 00:03:50 +0100 Subject: Added encryption for messages better API for sealing messages --- whisper/envelope.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'whisper/envelope.go') diff --git a/whisper/envelope.go b/whisper/envelope.go index 8e66a7bbb..eb80098ad 100644 --- a/whisper/envelope.go +++ b/whisper/envelope.go @@ -16,8 +16,8 @@ const ( ) type Envelope struct { - Expiry int32 // Whisper protocol specifies int32, really should be int64 - Ttl int32 // ^^^^^^ + Expiry uint32 // Whisper protocol specifies int32, really should be int64 + Ttl uint32 // ^^^^^^ Topics [][]byte Data []byte Nonce uint32 @@ -52,11 +52,11 @@ func (self *Envelope) Hash() Hash { func NewEnvelope(ttl time.Duration, topics [][]byte, data *Message) *Envelope { exp := time.Now().Add(ttl) - return &Envelope{int32(exp.Unix()), int32(ttl.Seconds()), topics, data.Bytes(), 0, Hash{}} + return &Envelope{uint32(exp.Unix()), uint32(ttl.Seconds()), topics, data.Bytes(), 0, Hash{}} } -func (self *Envelope) Seal() { - self.proveWork(DefaultPow) +func (self *Envelope) Seal(pow time.Duration) { + self.proveWork(pow) } func (self *Envelope) proveWork(dura time.Duration) { -- cgit From dda778eda7ad9b94acf14c3c91c1c29e711e170f Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 10 Dec 2014 14:17:32 +0100 Subject: Updated whisper messages to new crypto api + added tests --- whisper/envelope.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'whisper/envelope.go') diff --git a/whisper/envelope.go b/whisper/envelope.go index eb80098ad..359fa1568 100644 --- a/whisper/envelope.go +++ b/whisper/envelope.go @@ -2,7 +2,9 @@ package whisper import ( "bytes" + "crypto/ecdsa" "encoding/binary" + "fmt" "io" "time" @@ -59,6 +61,24 @@ func (self *Envelope) Seal(pow time.Duration) { self.proveWork(pow) } +func (self *Envelope) Open(prv *ecdsa.PrivateKey) (*Message, error) { + data := self.Data + if data[0] > 0 && len(data) < 66 { + return nil, fmt.Errorf("unable to open envelope. First bit set but len(data) < 66") + } + + if data[0] > 0 { + payload, err := crypto.Decrypt(prv, data[66:]) + if err != nil { + return nil, fmt.Errorf("unable to open envelope. Decrypt failed: %v", err) + } + + return NewMessage(payload), nil + } + + return NewMessage(data[1:]), nil +} + func (self *Envelope) proveWork(dura time.Duration) { var bestBit int d := make([]byte, 64) -- cgit From a17a1f9208f858601f6660dbd7f1b77dd9a3f3d9 Mon Sep 17 00:00:00 2001 From: obscuren Date: Fri, 12 Dec 2014 22:23:42 +0100 Subject: Implemented watching using filter package * Added filters / watches * Removed event dep --- whisper/envelope.go | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'whisper/envelope.go') diff --git a/whisper/envelope.go b/whisper/envelope.go index 359fa1568..683e88128 100644 --- a/whisper/envelope.go +++ b/whisper/envelope.go @@ -61,22 +61,27 @@ func (self *Envelope) Seal(pow time.Duration) { self.proveWork(pow) } -func (self *Envelope) Open(prv *ecdsa.PrivateKey) (*Message, error) { +func (self *Envelope) Open(prv *ecdsa.PrivateKey) (msg *Message, err error) { data := self.Data - if data[0] > 0 && len(data) < 66 { - return nil, fmt.Errorf("unable to open envelope. First bit set but len(data) < 66") - } - + var message Message + dataStart := 1 if data[0] > 0 { - payload, err := crypto.Decrypt(prv, data[66:]) + if len(data) < 66 { + return nil, fmt.Errorf("unable to open envelope. First bit set but len(data) < 66") + } + dataStart = 66 + message.Flags = data[0] + message.Signature = data[1:66] + } + message.Payload = data[dataStart:] + if prv != nil { + message.Payload, err = crypto.Decrypt(prv, message.Payload) if err != nil { return nil, fmt.Errorf("unable to open envelope. Decrypt failed: %v", err) } - - return NewMessage(payload), nil } - return NewMessage(data[1:]), nil + return &message, nil } func (self *Envelope) proveWork(dura time.Duration) { -- cgit