| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | package whisper | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2014-12-08 13:16:50 +01:00
										 |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2014-12-10 14:17:32 +01:00
										 |  |  | 	"crypto/ecdsa" | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	"sync" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-10 14:17:32 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2015-02-14 00:25:47 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto/ecies" | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/event/filter" | 
					
						
							| 
									
										
										
										
											2014-12-15 12:01:55 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger" | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/p2p" | 
					
						
							|  |  |  | 	"gopkg.in/fatih/set.v0" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MOVE ME | 
					
						
							|  |  |  | type Hash struct { | 
					
						
							|  |  |  | 	hash string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var EmptyHash Hash | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func H(hash []byte) Hash { | 
					
						
							|  |  |  | 	return Hash{string(hash)} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | func HS(hash string) Hash { | 
					
						
							|  |  |  | 	return Hash{hash} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-08 13:16:50 +01:00
										 |  |  | func (self Hash) Compare(other Hash) int { | 
					
						
							|  |  |  | 	return bytes.Compare([]byte(self.hash), []byte(other.hash)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | // MOVE ME END | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	statusMsg    = 0x0 | 
					
						
							|  |  |  | 	envelopesMsg = 0x01 | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | type MessageEvent struct { | 
					
						
							|  |  |  | 	To      *ecdsa.PrivateKey | 
					
						
							|  |  |  | 	From    *ecdsa.PublicKey | 
					
						
							|  |  |  | 	Message *Message | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | const DefaultTtl = 50 * time.Second | 
					
						
							| 
									
										
										
										
											2014-12-08 14:25:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 12:01:55 +01:00
										 |  |  | var wlogger = logger.NewLogger("SHH") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | type Whisper struct { | 
					
						
							|  |  |  | 	protocol p2p.Protocol | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 	filters  *filter.Filters | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mmu      sync.RWMutex | 
					
						
							|  |  |  | 	messages map[Hash]*Envelope | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 	expiry   map[uint32]*set.SetNonTS | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	quit chan struct{} | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-14 18:12:18 +01:00
										 |  |  | 	keys map[string]*ecdsa.PrivateKey | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | func New() *Whisper { | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	whisper := &Whisper{ | 
					
						
							|  |  |  | 		messages: make(map[Hash]*Envelope), | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 		filters:  filter.New(), | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 		expiry:   make(map[uint32]*set.SetNonTS), | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 		quit:     make(chan struct{}), | 
					
						
							| 
									
										
										
										
											2015-01-14 18:12:18 +01:00
										 |  |  | 		keys:     make(map[string]*ecdsa.PrivateKey), | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 	whisper.filters.Start() | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// p2p whisper sub protocol handler | 
					
						
							|  |  |  | 	whisper.protocol = p2p.Protocol{ | 
					
						
							|  |  |  | 		Name:    "shh", | 
					
						
							|  |  |  | 		Version: 2, | 
					
						
							|  |  |  | 		Length:  2, | 
					
						
							|  |  |  | 		Run:     whisper.msgHandler, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return whisper | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 12:01:55 +01:00
										 |  |  | func (self *Whisper) Start() { | 
					
						
							|  |  |  | 	wlogger.Infoln("Whisper started") | 
					
						
							|  |  |  | 	go self.update() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | func (self *Whisper) Stop() { | 
					
						
							|  |  |  | 	close(self.quit) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | func (self *Whisper) Send(envelope *Envelope) error { | 
					
						
							|  |  |  | 	return self.add(envelope) | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | func (self *Whisper) NewIdentity() *ecdsa.PrivateKey { | 
					
						
							|  |  |  | 	key, err := crypto.GenerateKey() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-14 18:12:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	self.keys[string(crypto.FromECDSAPub(&key.PublicKey))] = key | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return key | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-14 18:12:18 +01:00
										 |  |  | 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))] | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *Whisper) Watch(opts Filter) int { | 
					
						
							|  |  |  | 	return self.filters.Install(filter.Generic{ | 
					
						
							| 
									
										
										
										
											2015-02-05 15:00:59 -08:00
										 |  |  | 		Str1: string(crypto.FromECDSAPub(opts.To)), | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 		Str2: string(crypto.FromECDSAPub(opts.From)), | 
					
						
							| 
									
										
										
										
											2014-12-16 19:55:57 +01:00
										 |  |  | 		Data: bytesToMap(opts.Topics), | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 		Fn: func(data interface{}) { | 
					
						
							|  |  |  | 			opts.Fn(data.(*Message)) | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-13 13:36:44 +01:00
										 |  |  | func (self *Whisper) Messages(id int) (messages []*Message) { | 
					
						
							| 
									
										
										
										
											2015-01-12 20:36:45 +01:00
										 |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2015-01-13 13:36:44 +01:00
										 |  |  | 					messages = append(messages, msg) | 
					
						
							| 
									
										
										
										
											2015-01-12 20:36:45 +01:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-13 13:36:44 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return | 
					
						
							| 
									
										
										
										
											2015-01-12 20:36:45 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-08 13:16:50 +01:00
										 |  |  | // Main handler for passing whisper messages to whisper peer objects | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | func (self *Whisper) msgHandler(peer *p2p.Peer, ws p2p.MsgReadWriter) error { | 
					
						
							|  |  |  | 	wpeer := NewPeer(self, peer, ws) | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 	// initialise whisper peer (handshake/status) | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	if err := wpeer.init(); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-08 13:16:50 +01:00
										 |  |  | 	// kick of the main handler for broadcasting/managing envelopes | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	go wpeer.start() | 
					
						
							| 
									
										
										
										
											2014-12-08 13:16:50 +01:00
										 |  |  | 	defer wpeer.stop() | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-08 13:16:50 +01:00
										 |  |  | 	// Main *read* loop. Writing is done by the peer it self. | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	for { | 
					
						
							|  |  |  | 		msg, err := ws.ReadMsg() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-13 13:36:44 +01:00
										 |  |  | 		var envelopes []*Envelope | 
					
						
							|  |  |  | 		if err := msg.Decode(&envelopes); err != nil { | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 			peer.Infoln(err) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-13 13:36:44 +01:00
										 |  |  | 		for _, envelope := range envelopes { | 
					
						
							|  |  |  | 			if err := self.add(envelope); err != nil { | 
					
						
							|  |  |  | 				// TODO Punish peer here. Invalid envelope. | 
					
						
							|  |  |  | 				peer.Infoln(err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			wpeer.addKnown(envelope) | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-08 13:16:50 +01:00
										 |  |  | // takes care of adding envelopes to the messages pool. At this moment no sanity checks are being performed. | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | func (self *Whisper) add(envelope *Envelope) error { | 
					
						
							|  |  |  | 	if !envelope.valid() { | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 		return errors.New("invalid pow provided for envelope") | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	self.mmu.Lock() | 
					
						
							|  |  |  | 	defer self.mmu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 	hash := envelope.Hash() | 
					
						
							|  |  |  | 	self.messages[hash] = envelope | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	if self.expiry[envelope.Expiry] == nil { | 
					
						
							|  |  |  | 		self.expiry[envelope.Expiry] = set.NewNonTS() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if !self.expiry[envelope.Expiry].Has(hash) { | 
					
						
							|  |  |  | 		self.expiry[envelope.Expiry].Add(hash) | 
					
						
							| 
									
										
										
										
											2014-12-22 13:23:11 +01:00
										 |  |  | 		go self.postEvent(envelope) | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-30 13:24:20 +01:00
										 |  |  | 	wlogger.DebugDetailf("added whisper envelope %x\n", envelope) | 
					
						
							| 
									
										
										
										
											2015-01-13 13:36:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *Whisper) update() { | 
					
						
							|  |  |  | 	expire := time.NewTicker(800 * time.Millisecond) | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case <-expire.C: | 
					
						
							|  |  |  | 			self.expire() | 
					
						
							|  |  |  | 		case <-self.quit: | 
					
						
							|  |  |  | 			break out | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-08 13:16:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | func (self *Whisper) expire() { | 
					
						
							|  |  |  | 	self.mmu.Lock() | 
					
						
							|  |  |  | 	defer self.mmu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-10 00:03:50 +01:00
										 |  |  | 	now := uint32(time.Now().Unix()) | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	for then, hashSet := range self.expiry { | 
					
						
							|  |  |  | 		if then > now { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		hashSet.Each(func(v interface{}) bool { | 
					
						
							|  |  |  | 			delete(self.messages, v.(Hash)) | 
					
						
							|  |  |  | 			return true | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		self.expiry[then].Clear() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *Whisper) envelopes() (envelopes []*Envelope) { | 
					
						
							|  |  |  | 	self.mmu.RLock() | 
					
						
							|  |  |  | 	defer self.mmu.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	envelopes = make([]*Envelope, len(self.messages)) | 
					
						
							|  |  |  | 	i := 0 | 
					
						
							|  |  |  | 	for _, envelope := range self.messages { | 
					
						
							|  |  |  | 		envelopes[i] = envelope | 
					
						
							|  |  |  | 		i++ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | func (self *Whisper) postEvent(envelope *Envelope) { | 
					
						
							| 
									
										
										
										
											2015-01-12 20:36:45 +01:00
										 |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 	for _, key := range self.keys { | 
					
						
							| 
									
										
										
										
											2014-12-15 21:54:34 +01:00
										 |  |  | 		if message, err := envelope.Open(key); err == nil || (err != nil && err == ecies.ErrInvalidPublicKey) { | 
					
						
							| 
									
										
										
										
											2015-02-10 13:20:06 +01:00
										 |  |  | 			message.To = &key.PublicKey | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-12 20:36:45 +01:00
										 |  |  | 			return message, key | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-12 20:36:45 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil, nil | 
					
						
							| 
									
										
										
										
											2014-12-12 22:23:42 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | func (self *Whisper) Protocol() p2p.Protocol { | 
					
						
							|  |  |  | 	return self.protocol | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-01-12 20:36:45 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func createFilter(message *Message, topics [][]byte, key *ecdsa.PrivateKey) filter.Filter { | 
					
						
							|  |  |  | 	return filter.Generic{ | 
					
						
							| 
									
										
										
										
											2015-02-03 07:16:05 -08:00
										 |  |  | 		Str1: string(crypto.FromECDSAPub(&key.PublicKey)), Str2: string(crypto.FromECDSAPub(message.Recover())), | 
					
						
							| 
									
										
										
										
											2015-01-12 20:36:45 +01:00
										 |  |  | 		Data: bytesToMap(topics), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |