github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/pss/notify/notify.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 package notify 10 11 import ( 12 "crypto/ecdsa" 13 "fmt" 14 "sync" 15 16 "github.com/ethereum/go-ethereum/common/hexutil" 17 "github.com/ethereum/go-ethereum/crypto" 18 "github.com/ethereum/go-ethereum/p2p" 19 "github.com/ethereum/go-ethereum/rlp" 20 "github.com/ethereum/go-ethereum/swarm/log" 21 "github.com/ethereum/go-ethereum/swarm/pss" 22 ) 23 24 const ( 25 // 26 MsgCodeStart = iota 27 28 // 29 MsgCodeNotifyWithKey 30 31 // 32 MsgCodeNotify 33 34 // 35 MsgCodeStop 36 MsgCodeMax 37 ) 38 39 const ( 40 DefaultAddressLength = 1 41 symKeyLength = 32 // 42 ) 43 44 var ( 45 // 46 controlTopic = pss.Topic{0x00, 0x00, 0x00, 0x01} 47 ) 48 49 // 50 // 51 // 52 // 53 type Msg struct { 54 Code byte 55 Name []byte 56 Payload []byte 57 namestring string 58 } 59 60 // 61 func NewMsg(code byte, name string, payload []byte) *Msg { 62 return &Msg{ 63 Code: code, 64 Name: []byte(name), 65 Payload: payload, 66 namestring: name, 67 } 68 } 69 70 // 71 func NewMsgFromPayload(payload []byte) (*Msg, error) { 72 msg := &Msg{} 73 err := rlp.DecodeBytes(payload, msg) 74 if err != nil { 75 return nil, err 76 } 77 msg.namestring = string(msg.Name) 78 return msg, nil 79 } 80 81 // 82 type sendBin struct { 83 address pss.PssAddress 84 symKeyId string 85 count int 86 } 87 88 // 89 // 90 type notifier struct { 91 bins map[string]*sendBin 92 topic pss.Topic // 93 threshold int // 94 updateC <-chan []byte 95 quitC chan struct{} 96 } 97 98 func (n *notifier) removeSubscription() { 99 n.quitC <- struct{}{} 100 } 101 102 // 103 type subscription struct { 104 pubkeyId string 105 address pss.PssAddress 106 handler func(string, []byte) error 107 } 108 109 // 110 type Controller struct { 111 pss *pss.Pss 112 notifiers map[string]*notifier 113 subscriptions map[string]*subscription 114 mu sync.Mutex 115 } 116 117 // 118 func NewController(ps *pss.Pss) *Controller { 119 ctrl := &Controller{ 120 pss: ps, 121 notifiers: make(map[string]*notifier), 122 subscriptions: make(map[string]*subscription), 123 } 124 ctrl.pss.Register(&controlTopic, ctrl.Handler) 125 return ctrl 126 } 127 128 // 129 // 130 func (c *Controller) IsActive(name string) bool { 131 c.mu.Lock() 132 defer c.mu.Unlock() 133 return c.isActive(name) 134 } 135 136 func (c *Controller) isActive(name string) bool { 137 _, ok := c.notifiers[name] 138 return ok 139 } 140 141 // 142 // 143 // 144 // 145 func (c *Controller) Subscribe(name string, pubkey *ecdsa.PublicKey, address pss.PssAddress, handler func(string, []byte) error) error { 146 c.mu.Lock() 147 defer c.mu.Unlock() 148 msg := NewMsg(MsgCodeStart, name, c.pss.BaseAddr()) 149 c.pss.SetPeerPublicKey(pubkey, controlTopic, &address) 150 pubkeyId := hexutil.Encode(crypto.FromECDSAPub(pubkey)) 151 smsg, err := rlp.EncodeToBytes(msg) 152 if err != nil { 153 return err 154 } 155 err = c.pss.SendAsym(pubkeyId, controlTopic, smsg) 156 if err != nil { 157 return err 158 } 159 c.subscriptions[name] = &subscription{ 160 pubkeyId: pubkeyId, 161 address: address, 162 handler: handler, 163 } 164 return nil 165 } 166 167 // 168 // 169 func (c *Controller) Unsubscribe(name string) error { 170 c.mu.Lock() 171 defer c.mu.Unlock() 172 sub, ok := c.subscriptions[name] 173 if !ok { 174 return fmt.Errorf("Unknown subscription '%s'", name) 175 } 176 msg := NewMsg(MsgCodeStop, name, sub.address) 177 smsg, err := rlp.EncodeToBytes(msg) 178 if err != nil { 179 return err 180 } 181 err = c.pss.SendAsym(sub.pubkeyId, controlTopic, smsg) 182 if err != nil { 183 return err 184 } 185 delete(c.subscriptions, name) 186 return nil 187 } 188 189 // 190 // 191 // 192 // 193 // 194 func (c *Controller) NewNotifier(name string, threshold int, updateC <-chan []byte) (func(), error) { 195 c.mu.Lock() 196 if c.isActive(name) { 197 c.mu.Unlock() 198 return nil, fmt.Errorf("Notification service %s already exists in controller", name) 199 } 200 quitC := make(chan struct{}) 201 c.notifiers[name] = ¬ifier{ 202 bins: make(map[string]*sendBin), 203 topic: pss.BytesToTopic([]byte(name)), 204 threshold: threshold, 205 updateC: updateC, 206 quitC: quitC, 207 // 208 } 209 c.mu.Unlock() 210 go func() { 211 for { 212 select { 213 case <-quitC: 214 return 215 case data := <-updateC: 216 c.notify(name, data) 217 } 218 } 219 }() 220 221 return c.notifiers[name].removeSubscription, nil 222 } 223 224 // 225 // 226 func (c *Controller) RemoveNotifier(name string) error { 227 c.mu.Lock() 228 defer c.mu.Unlock() 229 currentNotifier, ok := c.notifiers[name] 230 if !ok { 231 return fmt.Errorf("Unknown notification service %s", name) 232 } 233 currentNotifier.removeSubscription() 234 delete(c.notifiers, name) 235 return nil 236 } 237 238 // 239 // 240 // 241 // 242 func (c *Controller) notify(name string, data []byte) error { 243 c.mu.Lock() 244 defer c.mu.Unlock() 245 if !c.isActive(name) { 246 return fmt.Errorf("Notification service %s doesn't exist", name) 247 } 248 msg := NewMsg(MsgCodeNotify, name, data) 249 smsg, err := rlp.EncodeToBytes(msg) 250 if err != nil { 251 return err 252 } 253 for _, m := range c.notifiers[name].bins { 254 log.Debug("sending pss notify", "name", name, "addr", fmt.Sprintf("%x", m.address), "topic", fmt.Sprintf("%x", c.notifiers[name].topic), "data", data) 255 go func(m *sendBin) { 256 err = c.pss.SendSym(m.symKeyId, c.notifiers[name].topic, smsg) 257 if err != nil { 258 log.Warn("Failed to send notify to addr %x: %v", m.address, err) 259 } 260 }(m) 261 } 262 return nil 263 } 264 265 // 266 // 267 // 268 func (c *Controller) addToBin(ntfr *notifier, address []byte) (symKeyId string, pssAddress pss.PssAddress, err error) { 269 270 // 271 if len(address) > ntfr.threshold { 272 address = address[:ntfr.threshold] 273 } 274 275 pssAddress = pss.PssAddress(address) 276 hexAddress := fmt.Sprintf("%x", address) 277 currentBin, ok := ntfr.bins[hexAddress] 278 if ok { 279 currentBin.count++ 280 symKeyId = currentBin.symKeyId 281 } else { 282 symKeyId, err = c.pss.GenerateSymmetricKey(ntfr.topic, &pssAddress, false) 283 if err != nil { 284 return "", nil, err 285 } 286 ntfr.bins[hexAddress] = &sendBin{ 287 address: address, 288 symKeyId: symKeyId, 289 count: 1, 290 } 291 } 292 return symKeyId, pssAddress, nil 293 } 294 295 func (c *Controller) handleStartMsg(msg *Msg, keyid string) (err error) { 296 297 keyidbytes, err := hexutil.Decode(keyid) 298 if err != nil { 299 return err 300 } 301 pubkey, err := crypto.UnmarshalPubkey(keyidbytes) 302 if err != nil { 303 return err 304 } 305 306 // 307 currentNotifier, ok := c.notifiers[msg.namestring] 308 if !ok { 309 return fmt.Errorf("Subscribe attempted on unknown resource '%s'", msg.namestring) 310 } 311 312 // 313 symKeyId, pssAddress, err := c.addToBin(currentNotifier, msg.Payload) 314 if err != nil { 315 return err 316 } 317 318 // 319 symkey, err := c.pss.GetSymmetricKey(symKeyId) 320 if err != nil { 321 return err 322 } 323 err = c.pss.SetPeerPublicKey(pubkey, controlTopic, &pssAddress) 324 if err != nil { 325 return err 326 } 327 328 // 329 notify := []byte{} 330 replyMsg := NewMsg(MsgCodeNotifyWithKey, msg.namestring, make([]byte, len(notify)+symKeyLength)) 331 copy(replyMsg.Payload, notify) 332 copy(replyMsg.Payload[len(notify):], symkey) 333 sReplyMsg, err := rlp.EncodeToBytes(replyMsg) 334 if err != nil { 335 return err 336 } 337 return c.pss.SendAsym(keyid, controlTopic, sReplyMsg) 338 } 339 340 func (c *Controller) handleNotifyWithKeyMsg(msg *Msg) error { 341 symkey := msg.Payload[len(msg.Payload)-symKeyLength:] 342 topic := pss.BytesToTopic(msg.Name) 343 344 // 345 updaterAddr := pss.PssAddress([]byte{}) 346 c.pss.SetSymmetricKey(symkey, topic, &updaterAddr, true) 347 c.pss.Register(&topic, c.Handler) 348 return c.subscriptions[msg.namestring].handler(msg.namestring, msg.Payload[:len(msg.Payload)-symKeyLength]) 349 } 350 351 func (c *Controller) handleStopMsg(msg *Msg) error { 352 // 353 currentNotifier, ok := c.notifiers[msg.namestring] 354 if !ok { 355 return fmt.Errorf("Unsubscribe attempted on unknown resource '%s'", msg.namestring) 356 } 357 358 // 359 address := msg.Payload 360 if len(msg.Payload) > currentNotifier.threshold { 361 address = address[:currentNotifier.threshold] 362 } 363 364 // 365 hexAddress := fmt.Sprintf("%x", address) 366 currentBin, ok := currentNotifier.bins[hexAddress] 367 if !ok { 368 return fmt.Errorf("found no active bin for address %s", hexAddress) 369 } 370 currentBin.count-- 371 if currentBin.count == 0 { // 372 delete(currentNotifier.bins, hexAddress) 373 } 374 return nil 375 } 376 377 // 378 // 379 func (c *Controller) Handler(smsg []byte, p *p2p.Peer, asymmetric bool, keyid string) error { 380 c.mu.Lock() 381 defer c.mu.Unlock() 382 log.Debug("notify controller handler", "keyid", keyid) 383 384 // 385 msg, err := NewMsgFromPayload(smsg) 386 if err != nil { 387 return err 388 } 389 390 switch msg.Code { 391 case MsgCodeStart: 392 return c.handleStartMsg(msg, keyid) 393 case MsgCodeNotifyWithKey: 394 return c.handleNotifyWithKeyMsg(msg) 395 case MsgCodeNotify: 396 return c.subscriptions[msg.namestring].handler(msg.namestring, msg.Payload) 397 case MsgCodeStop: 398 return c.handleStopMsg(msg) 399 } 400 401 return fmt.Errorf("Invalid message code: %d", msg.Code) 402 }