github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/whisper/whisperv5/filter.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:51</date> 10 //</624342688677761024> 11 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 // 25 // 26 // 27 28 package whisperv5 29 30 import ( 31 "crypto/ecdsa" 32 "fmt" 33 "sync" 34 35 "github.com/ethereum/go-ethereum/common" 36 "github.com/ethereum/go-ethereum/crypto" 37 "github.com/ethereum/go-ethereum/log" 38 ) 39 40 type Filter struct { 41 Src *ecdsa.PublicKey // 42 KeyAsym *ecdsa.PrivateKey // 43 KeySym []byte // 44 Topics [][]byte // 45 PoW float64 // 46 AllowP2P bool // 47 SymKeyHash common.Hash // 48 49 Messages map[common.Hash]*ReceivedMessage 50 mutex sync.RWMutex 51 } 52 53 type Filters struct { 54 watchers map[string]*Filter 55 whisper *Whisper 56 mutex sync.RWMutex 57 } 58 59 func NewFilters(w *Whisper) *Filters { 60 return &Filters{ 61 watchers: make(map[string]*Filter), 62 whisper: w, 63 } 64 } 65 66 func (fs *Filters) Install(watcher *Filter) (string, error) { 67 if watcher.Messages == nil { 68 watcher.Messages = make(map[common.Hash]*ReceivedMessage) 69 } 70 71 id, err := GenerateRandomID() 72 if err != nil { 73 return "", err 74 } 75 76 fs.mutex.Lock() 77 defer fs.mutex.Unlock() 78 79 if fs.watchers[id] != nil { 80 return "", fmt.Errorf("failed to generate unique ID") 81 } 82 83 if watcher.expectsSymmetricEncryption() { 84 watcher.SymKeyHash = crypto.Keccak256Hash(watcher.KeySym) 85 } 86 87 fs.watchers[id] = watcher 88 return id, err 89 } 90 91 func (fs *Filters) Uninstall(id string) bool { 92 fs.mutex.Lock() 93 defer fs.mutex.Unlock() 94 if fs.watchers[id] != nil { 95 delete(fs.watchers, id) 96 return true 97 } 98 return false 99 } 100 101 func (fs *Filters) Get(id string) *Filter { 102 fs.mutex.RLock() 103 defer fs.mutex.RUnlock() 104 return fs.watchers[id] 105 } 106 107 func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) { 108 var msg *ReceivedMessage 109 110 fs.mutex.RLock() 111 defer fs.mutex.RUnlock() 112 113 i := -1 // 114 for _, watcher := range fs.watchers { 115 i++ 116 if p2pMessage && !watcher.AllowP2P { 117 log.Trace(fmt.Sprintf("msg [%x], filter [%d]: p2p messages are not allowed", env.Hash(), i)) 118 continue 119 } 120 121 var match bool 122 if msg != nil { 123 match = watcher.MatchMessage(msg) 124 } else { 125 match = watcher.MatchEnvelope(env) 126 if match { 127 msg = env.Open(watcher) 128 if msg == nil { 129 log.Trace("processing message: failed to open", "message", env.Hash().Hex(), "filter", i) 130 } 131 } else { 132 log.Trace("processing message: does not match", "message", env.Hash().Hex(), "filter", i) 133 } 134 } 135 136 if match && msg != nil { 137 log.Trace("processing message: decrypted", "hash", env.Hash().Hex()) 138 if watcher.Src == nil || IsPubKeyEqual(msg.Src, watcher.Src) { 139 watcher.Trigger(msg) 140 } 141 } 142 } 143 } 144 145 func (f *Filter) processEnvelope(env *Envelope) *ReceivedMessage { 146 if f.MatchEnvelope(env) { 147 msg := env.Open(f) 148 if msg != nil { 149 return msg 150 } else { 151 log.Trace("processing envelope: failed to open", "hash", env.Hash().Hex()) 152 } 153 } else { 154 log.Trace("processing envelope: does not match", "hash", env.Hash().Hex()) 155 } 156 return nil 157 } 158 159 func (f *Filter) expectsAsymmetricEncryption() bool { 160 return f.KeyAsym != nil 161 } 162 163 func (f *Filter) expectsSymmetricEncryption() bool { 164 return f.KeySym != nil 165 } 166 167 func (f *Filter) Trigger(msg *ReceivedMessage) { 168 f.mutex.Lock() 169 defer f.mutex.Unlock() 170 171 if _, exist := f.Messages[msg.EnvelopeHash]; !exist { 172 f.Messages[msg.EnvelopeHash] = msg 173 } 174 } 175 176 func (f *Filter) Retrieve() (all []*ReceivedMessage) { 177 f.mutex.Lock() 178 defer f.mutex.Unlock() 179 180 all = make([]*ReceivedMessage, 0, len(f.Messages)) 181 for _, msg := range f.Messages { 182 all = append(all, msg) 183 } 184 185 f.Messages = make(map[common.Hash]*ReceivedMessage) // 186 return all 187 } 188 189 func (f *Filter) MatchMessage(msg *ReceivedMessage) bool { 190 if f.PoW > 0 && msg.PoW < f.PoW { 191 return false 192 } 193 194 if f.expectsAsymmetricEncryption() && msg.isAsymmetricEncryption() { 195 return IsPubKeyEqual(&f.KeyAsym.PublicKey, msg.Dst) && f.MatchTopic(msg.Topic) 196 } else if f.expectsSymmetricEncryption() && msg.isSymmetricEncryption() { 197 return f.SymKeyHash == msg.SymKeyHash && f.MatchTopic(msg.Topic) 198 } 199 return false 200 } 201 202 func (f *Filter) MatchEnvelope(envelope *Envelope) bool { 203 if f.PoW > 0 && envelope.pow < f.PoW { 204 return false 205 } 206 207 if f.expectsAsymmetricEncryption() && envelope.isAsymmetric() { 208 return f.MatchTopic(envelope.Topic) 209 } else if f.expectsSymmetricEncryption() && envelope.IsSymmetric() { 210 return f.MatchTopic(envelope.Topic) 211 } 212 return false 213 } 214 215 func (f *Filter) MatchTopic(topic TopicType) bool { 216 if len(f.Topics) == 0 { 217 // 218 return true 219 } 220 221 for _, bt := range f.Topics { 222 if matchSingleTopic(topic, bt) { 223 return true 224 } 225 } 226 return false 227 } 228 229 func matchSingleTopic(topic TopicType, bt []byte) bool { 230 if len(bt) > TopicLength { 231 bt = bt[:TopicLength] 232 } 233 234 if len(bt) == 0 { 235 return false 236 } 237 238 for j, b := range bt { 239 if topic[j] != b { 240 return false 241 } 242 } 243 return true 244 } 245 246 func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool { 247 if !ValidatePublicKey(a) { 248 return false 249 } else if !ValidatePublicKey(b) { 250 return false 251 } 252 // 253 return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0 254 } 255