github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/whisper/whisperv6/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 //</624450125330124800> 11 12 13 package whisperv6 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 //筛选器表示耳语消息筛选器 26 type Filter struct { 27 Src *ecdsa.PublicKey //邮件的发件人 28 KeyAsym *ecdsa.PrivateKey //收件人的私钥 29 KeySym []byte //与主题关联的键 30 Topics [][]byte //筛选邮件的主题 31 PoW float64 //耳语规范中所述的工作证明 32 AllowP2P bool //指示此筛选器是否对直接对等消息感兴趣 33 SymKeyHash common.Hash //优化所需的对称密钥的keccak256hash 34 id string //唯一标识符 35 36 Messages map[common.Hash]*ReceivedMessage 37 mutex sync.RWMutex 38 } 39 40 //筛选器表示筛选器的集合 41 type Filters struct { 42 watchers map[string]*Filter 43 44 topicMatcher map[TopicType]map[*Filter]struct{} //将主题映射到在消息与该主题匹配时感兴趣收到通知的筛选器 45 allTopicsMatcher map[*Filter]struct{} //列出将通知新邮件的所有筛选器,无论其主题是什么 46 47 whisper *Whisper 48 mutex sync.RWMutex 49 } 50 51 //newfilters返回新创建的筛选器集合 52 func NewFilters(w *Whisper) *Filters { 53 return &Filters{ 54 watchers: make(map[string]*Filter), 55 topicMatcher: make(map[TopicType]map[*Filter]struct{}), 56 allTopicsMatcher: make(map[*Filter]struct{}), 57 whisper: w, 58 } 59 } 60 61 //安装将向筛选器集合添加新筛选器 62 func (fs *Filters) Install(watcher *Filter) (string, error) { 63 if watcher.KeySym != nil && watcher.KeyAsym != nil { 64 return "", fmt.Errorf("filters must choose between symmetric and asymmetric keys") 65 } 66 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 watcher.id = id 88 fs.watchers[id] = watcher 89 fs.addTopicMatcher(watcher) 90 return id, err 91 } 92 93 //卸载将删除已从中指定ID的筛选器 94 //筛选器集合 95 func (fs *Filters) Uninstall(id string) bool { 96 fs.mutex.Lock() 97 defer fs.mutex.Unlock() 98 if fs.watchers[id] != nil { 99 fs.removeFromTopicMatchers(fs.watchers[id]) 100 delete(fs.watchers, id) 101 return true 102 } 103 return false 104 } 105 106 //addTopicMatcher向主题匹配器添加一个筛选器。 107 //如果过滤器的主题数组为空,将对每个主题进行尝试。 108 //否则,将在指定的主题上进行尝试。 109 func (fs *Filters) addTopicMatcher(watcher *Filter) { 110 if len(watcher.Topics) == 0 { 111 fs.allTopicsMatcher[watcher] = struct{}{} 112 } else { 113 for _, t := range watcher.Topics { 114 topic := BytesToTopic(t) 115 if fs.topicMatcher[topic] == nil { 116 fs.topicMatcher[topic] = make(map[*Filter]struct{}) 117 } 118 fs.topicMatcher[topic][watcher] = struct{}{} 119 } 120 } 121 } 122 123 //removeFromTopicMatchers从主题匹配器中删除筛选器 124 func (fs *Filters) removeFromTopicMatchers(watcher *Filter) { 125 delete(fs.allTopicsMatcher, watcher) 126 for _, topic := range watcher.Topics { 127 delete(fs.topicMatcher[BytesToTopic(topic)], watcher) 128 } 129 } 130 131 //GetWatchersByTopic返回一个包含以下筛选器的切片: 132 //匹配特定主题 133 func (fs *Filters) getWatchersByTopic(topic TopicType) []*Filter { 134 res := make([]*Filter, 0, len(fs.allTopicsMatcher)) 135 for watcher := range fs.allTopicsMatcher { 136 res = append(res, watcher) 137 } 138 for watcher := range fs.topicMatcher[topic] { 139 res = append(res, watcher) 140 } 141 return res 142 } 143 144 //get返回集合中具有特定ID的筛选器 145 func (fs *Filters) Get(id string) *Filter { 146 fs.mutex.RLock() 147 defer fs.mutex.RUnlock() 148 return fs.watchers[id] 149 } 150 151 //通知观察程序通知已声明感兴趣的任何筛选器 152 //信封主题。 153 func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) { 154 var msg *ReceivedMessage 155 156 fs.mutex.RLock() 157 defer fs.mutex.RUnlock() 158 159 candidates := fs.getWatchersByTopic(env.Topic) 160 for _, watcher := range candidates { 161 if p2pMessage && !watcher.AllowP2P { 162 log.Trace(fmt.Sprintf("msg [%x], filter [%s]: p2p messages are not allowed", env.Hash(), watcher.id)) 163 continue 164 } 165 166 var match bool 167 if msg != nil { 168 match = watcher.MatchMessage(msg) 169 } else { 170 match = watcher.MatchEnvelope(env) 171 if match { 172 msg = env.Open(watcher) 173 if msg == nil { 174 log.Trace("processing message: failed to open", "message", env.Hash().Hex(), "filter", watcher.id) 175 } 176 } else { 177 log.Trace("processing message: does not match", "message", env.Hash().Hex(), "filter", watcher.id) 178 } 179 } 180 181 if match && msg != nil { 182 log.Trace("processing message: decrypted", "hash", env.Hash().Hex()) 183 if watcher.Src == nil || IsPubKeyEqual(msg.Src, watcher.Src) { 184 watcher.Trigger(msg) 185 } 186 } 187 } 188 } 189 190 func (f *Filter) expectsAsymmetricEncryption() bool { 191 return f.KeyAsym != nil 192 } 193 194 func (f *Filter) expectsSymmetricEncryption() bool { 195 return f.KeySym != nil 196 } 197 198 //触发器将未知消息添加到筛选器的列表中 199 //收到的消息。 200 func (f *Filter) Trigger(msg *ReceivedMessage) { 201 f.mutex.Lock() 202 defer f.mutex.Unlock() 203 204 if _, exist := f.Messages[msg.EnvelopeHash]; !exist { 205 f.Messages[msg.EnvelopeHash] = msg 206 } 207 } 208 209 //检索将返回所有相关联的已接收消息的列表 210 //过滤器。 211 func (f *Filter) Retrieve() (all []*ReceivedMessage) { 212 f.mutex.Lock() 213 defer f.mutex.Unlock() 214 215 all = make([]*ReceivedMessage, 0, len(f.Messages)) 216 for _, msg := range f.Messages { 217 all = append(all, msg) 218 } 219 220 f.Messages = make(map[common.Hash]*ReceivedMessage) //删除旧邮件 221 return all 222 } 223 224 //MatchMessage检查筛选器是否匹配已解密的 225 //消息(即已经由 226 //匹配前一个筛选器选中的信封)。 227 //这里不检查主题,因为这是由主题匹配器完成的。 228 func (f *Filter) MatchMessage(msg *ReceivedMessage) bool { 229 if f.PoW > 0 && msg.PoW < f.PoW { 230 return false 231 } 232 233 if f.expectsAsymmetricEncryption() && msg.isAsymmetricEncryption() { 234 return IsPubKeyEqual(&f.KeyAsym.PublicKey, msg.Dst) 235 } else if f.expectsSymmetricEncryption() && msg.isSymmetricEncryption() { 236 return f.SymKeyHash == msg.SymKeyHash 237 } 238 return false 239 } 240 241 //匹配信封检查是否值得解密消息。如果 242 //它返回“true”,要求客户端代码尝试解密 243 //然后调用matchmessage。 244 //这里不检查主题,因为这是由主题匹配器完成的。 245 func (f *Filter) MatchEnvelope(envelope *Envelope) bool { 246 return f.PoW <= 0 || envelope.pow >= f.PoW 247 } 248 249 //isubkeyEqual检查两个公钥是否相等 250 func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool { 251 if !ValidatePublicKey(a) { 252 return false 253 } else if !ValidatePublicKey(b) { 254 return false 255 } 256 //曲线总是一样的,只要比较点 257 return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0 258 } 259