github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/whisper/whisperv6/filter.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 // 10 // 11 // 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 25 package whisperv6 26 27 import ( 28 "crypto/ecdsa" 29 "fmt" 30 "sync" 31 32 "github.com/ethereum/go-ethereum/common" 33 "github.com/ethereum/go-ethereum/crypto" 34 "github.com/ethereum/go-ethereum/log" 35 ) 36 37 // 38 type Filter struct { 39 Src *ecdsa.PublicKey // 40 KeyAsym *ecdsa.PrivateKey // 41 KeySym []byte // 42 Topics [][]byte // 43 PoW float64 // 44 AllowP2P bool // 45 SymKeyHash common.Hash // 46 id string // 47 48 Messages map[common.Hash]*ReceivedMessage 49 mutex sync.RWMutex 50 } 51 52 // 53 type Filters struct { 54 watchers map[string]*Filter 55 56 topicMatcher map[TopicType]map[*Filter]struct{} // 57 allTopicsMatcher map[*Filter]struct{} // 58 59 whisper *Whisper 60 mutex sync.RWMutex 61 } 62 63 // 64 func NewFilters(w *Whisper) *Filters { 65 return &Filters{ 66 watchers: make(map[string]*Filter), 67 topicMatcher: make(map[TopicType]map[*Filter]struct{}), 68 allTopicsMatcher: make(map[*Filter]struct{}), 69 whisper: w, 70 } 71 } 72 73 // 74 func (fs *Filters) Install(watcher *Filter) (string, error) { 75 if watcher.KeySym != nil && watcher.KeyAsym != nil { 76 return "", fmt.Errorf("filters must choose between symmetric and asymmetric keys") 77 } 78 79 if watcher.Messages == nil { 80 watcher.Messages = make(map[common.Hash]*ReceivedMessage) 81 } 82 83 id, err := GenerateRandomID() 84 if err != nil { 85 return "", err 86 } 87 88 fs.mutex.Lock() 89 defer fs.mutex.Unlock() 90 91 if fs.watchers[id] != nil { 92 return "", fmt.Errorf("failed to generate unique ID") 93 } 94 95 if watcher.expectsSymmetricEncryption() { 96 watcher.SymKeyHash = crypto.Keccak256Hash(watcher.KeySym) 97 } 98 99 watcher.id = id 100 fs.watchers[id] = watcher 101 fs.addTopicMatcher(watcher) 102 return id, err 103 } 104 105 // 106 // 107 func (fs *Filters) Uninstall(id string) bool { 108 fs.mutex.Lock() 109 defer fs.mutex.Unlock() 110 if fs.watchers[id] != nil { 111 fs.removeFromTopicMatchers(fs.watchers[id]) 112 delete(fs.watchers, id) 113 return true 114 } 115 return false 116 } 117 118 // 119 // 120 // 121 func (fs *Filters) addTopicMatcher(watcher *Filter) { 122 if len(watcher.Topics) == 0 { 123 fs.allTopicsMatcher[watcher] = struct{}{} 124 } else { 125 for _, t := range watcher.Topics { 126 topic := BytesToTopic(t) 127 if fs.topicMatcher[topic] == nil { 128 fs.topicMatcher[topic] = make(map[*Filter]struct{}) 129 } 130 fs.topicMatcher[topic][watcher] = struct{}{} 131 } 132 } 133 } 134 135 // 136 func (fs *Filters) removeFromTopicMatchers(watcher *Filter) { 137 delete(fs.allTopicsMatcher, watcher) 138 for _, topic := range watcher.Topics { 139 delete(fs.topicMatcher[BytesToTopic(topic)], watcher) 140 } 141 } 142 143 // 144 // 145 func (fs *Filters) getWatchersByTopic(topic TopicType) []*Filter { 146 res := make([]*Filter, 0, len(fs.allTopicsMatcher)) 147 for watcher := range fs.allTopicsMatcher { 148 res = append(res, watcher) 149 } 150 for watcher := range fs.topicMatcher[topic] { 151 res = append(res, watcher) 152 } 153 return res 154 } 155 156 // 157 func (fs *Filters) Get(id string) *Filter { 158 fs.mutex.RLock() 159 defer fs.mutex.RUnlock() 160 return fs.watchers[id] 161 } 162 163 // 164 // 165 func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) { 166 var msg *ReceivedMessage 167 168 fs.mutex.RLock() 169 defer fs.mutex.RUnlock() 170 171 candidates := fs.getWatchersByTopic(env.Topic) 172 for _, watcher := range candidates { 173 if p2pMessage && !watcher.AllowP2P { 174 log.Trace(fmt.Sprintf("msg [%x], filter [%s]: p2p messages are not allowed", env.Hash(), watcher.id)) 175 continue 176 } 177 178 var match bool 179 if msg != nil { 180 match = watcher.MatchMessage(msg) 181 } else { 182 match = watcher.MatchEnvelope(env) 183 if match { 184 msg = env.Open(watcher) 185 if msg == nil { 186 log.Trace("processing message: failed to open", "message", env.Hash().Hex(), "filter", watcher.id) 187 } 188 } else { 189 log.Trace("processing message: does not match", "message", env.Hash().Hex(), "filter", watcher.id) 190 } 191 } 192 193 if match && msg != nil { 194 log.Trace("processing message: decrypted", "hash", env.Hash().Hex()) 195 if watcher.Src == nil || IsPubKeyEqual(msg.Src, watcher.Src) { 196 watcher.Trigger(msg) 197 } 198 } 199 } 200 } 201 202 func (f *Filter) expectsAsymmetricEncryption() bool { 203 return f.KeyAsym != nil 204 } 205 206 func (f *Filter) expectsSymmetricEncryption() bool { 207 return f.KeySym != nil 208 } 209 210 // 211 // 212 func (f *Filter) Trigger(msg *ReceivedMessage) { 213 f.mutex.Lock() 214 defer f.mutex.Unlock() 215 216 if _, exist := f.Messages[msg.EnvelopeHash]; !exist { 217 f.Messages[msg.EnvelopeHash] = msg 218 } 219 } 220 221 // 222 // 223 func (f *Filter) Retrieve() (all []*ReceivedMessage) { 224 f.mutex.Lock() 225 defer f.mutex.Unlock() 226 227 all = make([]*ReceivedMessage, 0, len(f.Messages)) 228 for _, msg := range f.Messages { 229 all = append(all, msg) 230 } 231 232 f.Messages = make(map[common.Hash]*ReceivedMessage) // 233 return all 234 } 235 236 // 237 // 238 // 239 // 240 func (f *Filter) MatchMessage(msg *ReceivedMessage) bool { 241 if f.PoW > 0 && msg.PoW < f.PoW { 242 return false 243 } 244 245 if f.expectsAsymmetricEncryption() && msg.isAsymmetricEncryption() { 246 return IsPubKeyEqual(&f.KeyAsym.PublicKey, msg.Dst) 247 } else if f.expectsSymmetricEncryption() && msg.isSymmetricEncryption() { 248 return f.SymKeyHash == msg.SymKeyHash 249 } 250 return false 251 } 252 253 // 254 // 255 // 256 // 257 func (f *Filter) MatchEnvelope(envelope *Envelope) bool { 258 return f.PoW <= 0 || envelope.pow >= f.PoW 259 } 260 261 // 262 func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool { 263 if !ValidatePublicKey(a) { 264 return false 265 } else if !ValidatePublicKey(b) { 266 return false 267 } 268 // 269 return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0 270 }