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