github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/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 19:16:46</date> 10 //</624450124365434880> 11 12 13 package whisperv5 14 15 import ( 16 "crypto/ecdsa" 17 "fmt" 18 "sync" 19 20 "github.com/ethereum/go-ethereum/common" 21 "github.com/ethereum/go-ethereum/crypto" 22 "github.com/ethereum/go-ethereum/log" 23 ) 24 25 type Filter struct { 26 Src *ecdsa.PublicKey //邮件的发件人 27 KeyAsym *ecdsa.PrivateKey //收件人的私钥 28 KeySym []byte //与主题关联的键 29 Topics [][]byte //筛选邮件的主题 30 PoW float64 //耳语规范中所述的工作证明 31 AllowP2P bool //指示此筛选器是否对直接对等消息感兴趣 32 SymKeyHash common.Hash //优化所需的对称密钥的keccak256hash 33 34 Messages map[common.Hash]*ReceivedMessage 35 mutex sync.RWMutex 36 } 37 38 type Filters struct { 39 watchers map[string]*Filter 40 whisper *Whisper 41 mutex sync.RWMutex 42 } 43 44 func NewFilters(w *Whisper) *Filters { 45 return &Filters{ 46 watchers: make(map[string]*Filter), 47 whisper: w, 48 } 49 } 50 51 func (fs *Filters) Install(watcher *Filter) (string, error) { 52 if watcher.Messages == nil { 53 watcher.Messages = make(map[common.Hash]*ReceivedMessage) 54 } 55 56 id, err := GenerateRandomID() 57 if err != nil { 58 return "", err 59 } 60 61 fs.mutex.Lock() 62 defer fs.mutex.Unlock() 63 64 if fs.watchers[id] != nil { 65 return "", fmt.Errorf("failed to generate unique ID") 66 } 67 68 if watcher.expectsSymmetricEncryption() { 69 watcher.SymKeyHash = crypto.Keccak256Hash(watcher.KeySym) 70 } 71 72 fs.watchers[id] = watcher 73 return id, err 74 } 75 76 func (fs *Filters) Uninstall(id string) bool { 77 fs.mutex.Lock() 78 defer fs.mutex.Unlock() 79 if fs.watchers[id] != nil { 80 delete(fs.watchers, id) 81 return true 82 } 83 return false 84 } 85 86 func (fs *Filters) Get(id string) *Filter { 87 fs.mutex.RLock() 88 defer fs.mutex.RUnlock() 89 return fs.watchers[id] 90 } 91 92 func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) { 93 var msg *ReceivedMessage 94 95 fs.mutex.RLock() 96 defer fs.mutex.RUnlock() 97 98 i := -1 //仅用于日志信息 99 for _, watcher := range fs.watchers { 100 i++ 101 if p2pMessage && !watcher.AllowP2P { 102 log.Trace(fmt.Sprintf("msg [%x], filter [%d]: p2p messages are not allowed", env.Hash(), i)) 103 continue 104 } 105 106 var match bool 107 if msg != nil { 108 match = watcher.MatchMessage(msg) 109 } else { 110 match = watcher.MatchEnvelope(env) 111 if match { 112 msg = env.Open(watcher) 113 if msg == nil { 114 log.Trace("processing message: failed to open", "message", env.Hash().Hex(), "filter", i) 115 } 116 } else { 117 log.Trace("processing message: does not match", "message", env.Hash().Hex(), "filter", i) 118 } 119 } 120 121 if match && msg != nil { 122 log.Trace("processing message: decrypted", "hash", env.Hash().Hex()) 123 if watcher.Src == nil || IsPubKeyEqual(msg.Src, watcher.Src) { 124 watcher.Trigger(msg) 125 } 126 } 127 } 128 } 129 130 func (f *Filter) processEnvelope(env *Envelope) *ReceivedMessage { 131 if f.MatchEnvelope(env) { 132 msg := env.Open(f) 133 if msg != nil { 134 return msg 135 } else { 136 log.Trace("processing envelope: failed to open", "hash", env.Hash().Hex()) 137 } 138 } else { 139 log.Trace("processing envelope: does not match", "hash", env.Hash().Hex()) 140 } 141 return nil 142 } 143 144 func (f *Filter) expectsAsymmetricEncryption() bool { 145 return f.KeyAsym != nil 146 } 147 148 func (f *Filter) expectsSymmetricEncryption() bool { 149 return f.KeySym != nil 150 } 151 152 func (f *Filter) Trigger(msg *ReceivedMessage) { 153 f.mutex.Lock() 154 defer f.mutex.Unlock() 155 156 if _, exist := f.Messages[msg.EnvelopeHash]; !exist { 157 f.Messages[msg.EnvelopeHash] = msg 158 } 159 } 160 161 func (f *Filter) Retrieve() (all []*ReceivedMessage) { 162 f.mutex.Lock() 163 defer f.mutex.Unlock() 164 165 all = make([]*ReceivedMessage, 0, len(f.Messages)) 166 for _, msg := range f.Messages { 167 all = append(all, msg) 168 } 169 170 f.Messages = make(map[common.Hash]*ReceivedMessage) //删除旧邮件 171 return all 172 } 173 174 func (f *Filter) MatchMessage(msg *ReceivedMessage) bool { 175 if f.PoW > 0 && msg.PoW < f.PoW { 176 return false 177 } 178 179 if f.expectsAsymmetricEncryption() && msg.isAsymmetricEncryption() { 180 return IsPubKeyEqual(&f.KeyAsym.PublicKey, msg.Dst) && f.MatchTopic(msg.Topic) 181 } else if f.expectsSymmetricEncryption() && msg.isSymmetricEncryption() { 182 return f.SymKeyHash == msg.SymKeyHash && f.MatchTopic(msg.Topic) 183 } 184 return false 185 } 186 187 func (f *Filter) MatchEnvelope(envelope *Envelope) bool { 188 if f.PoW > 0 && envelope.pow < f.PoW { 189 return false 190 } 191 192 if f.expectsAsymmetricEncryption() && envelope.isAsymmetric() { 193 return f.MatchTopic(envelope.Topic) 194 } else if f.expectsSymmetricEncryption() && envelope.IsSymmetric() { 195 return f.MatchTopic(envelope.Topic) 196 } 197 return false 198 } 199 200 func (f *Filter) MatchTopic(topic TopicType) bool { 201 if len(f.Topics) == 0 { 202 //任何主题匹配 203 return true 204 } 205 206 for _, bt := range f.Topics { 207 if matchSingleTopic(topic, bt) { 208 return true 209 } 210 } 211 return false 212 } 213 214 func matchSingleTopic(topic TopicType, bt []byte) bool { 215 if len(bt) > TopicLength { 216 bt = bt[:TopicLength] 217 } 218 219 if len(bt) == 0 { 220 return false 221 } 222 223 for j, b := range bt { 224 if topic[j] != b { 225 return false 226 } 227 } 228 return true 229 } 230 231 func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool { 232 if !ValidatePublicKey(a) { 233 return false 234 } else if !ValidatePublicKey(b) { 235 return false 236 } 237 //曲线总是一样的,只要比较点 238 return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0 239 } 240