github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/pss/pss.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:44</date> 10 //</624450117008625664> 11 12 13 package pss 14 15 import ( 16 "bytes" 17 "context" 18 "crypto/ecdsa" 19 "crypto/rand" 20 "errors" 21 "fmt" 22 "hash" 23 "sync" 24 "time" 25 26 "github.com/ethereum/go-ethereum/common" 27 "github.com/ethereum/go-ethereum/crypto" 28 "github.com/ethereum/go-ethereum/metrics" 29 "github.com/ethereum/go-ethereum/p2p" 30 "github.com/ethereum/go-ethereum/p2p/enode" 31 "github.com/ethereum/go-ethereum/p2p/protocols" 32 "github.com/ethereum/go-ethereum/rpc" 33 "github.com/ethereum/go-ethereum/swarm/log" 34 "github.com/ethereum/go-ethereum/swarm/network" 35 "github.com/ethereum/go-ethereum/swarm/pot" 36 "github.com/ethereum/go-ethereum/swarm/storage" 37 whisper "github.com/ethereum/go-ethereum/whisper/whisperv5" 38 "golang.org/x/crypto/sha3" 39 ) 40 41 const ( 42 defaultPaddingByteSize = 16 43 DefaultMsgTTL = time.Second * 120 44 defaultDigestCacheTTL = time.Second * 10 45 defaultSymKeyCacheCapacity = 512 46 digestLength = 32 //用于PSS缓存的摘要的字节长度(当前与Swarm Chunk哈希相同) 47 defaultWhisperWorkTime = 3 48 defaultWhisperPoW = 0.0000000001 49 defaultMaxMsgSize = 1024 * 1024 50 defaultCleanInterval = time.Second * 60 * 10 51 defaultOutboxCapacity = 100000 52 pssProtocolName = "pss" 53 pssVersion = 2 54 hasherCount = 8 55 ) 56 57 var ( 58 addressLength = len(pot.Address{}) 59 ) 60 61 //缓存用于防止反向路由 62 //也将有助于防洪机制 63 //和邮箱实现 64 type pssCacheEntry struct { 65 expiresAt time.Time 66 } 67 68 //允许访问p2p.protocols.peer.send的抽象 69 type senderPeer interface { 70 Info() *p2p.PeerInfo 71 ID() enode.ID 72 Address() []byte 73 Send(context.Context, interface{}) error 74 } 75 76 //每键对等相关信息 77 //成员“protected”防止对实例进行垃圾收集 78 type pssPeer struct { 79 lastSeen time.Time 80 address PssAddress 81 protected bool 82 } 83 84 //PSS配置参数 85 type PssParams struct { 86 MsgTTL time.Duration 87 CacheTTL time.Duration 88 privateKey *ecdsa.PrivateKey 89 SymKeyCacheCapacity int 90 AllowRaw bool //如果为真,则允许在不使用内置PSS加密的情况下发送和接收消息 91 } 92 93 //PSS的正常默认值 94 func NewPssParams() *PssParams { 95 return &PssParams{ 96 MsgTTL: DefaultMsgTTL, 97 CacheTTL: defaultDigestCacheTTL, 98 SymKeyCacheCapacity: defaultSymKeyCacheCapacity, 99 } 100 } 101 102 func (params *PssParams) WithPrivateKey(privatekey *ecdsa.PrivateKey) *PssParams { 103 params.privateKey = privatekey 104 return params 105 } 106 107 //顶级PSS对象,负责消息发送、接收、解密和加密、消息处理程序调度器和消息转发。 108 // 109 //实现节点服务 110 type Pss struct { 111 *network.Kademlia //我们可以从这里得到卡德米利亚的地址 112 privateKey *ecdsa.PrivateKey //PSS可以拥有自己的独立密钥 113 w *whisper.Whisper //密钥和加密后端 114 auxAPIs []rpc.API //内置(握手、测试)可以添加API 115 116 //发送和转发 117 fwdPool map[string]*protocols.Peer //跟踪PSSMSG路由层上的所有对等端 118 fwdPoolMu sync.RWMutex 119 fwdCache map[pssDigest]pssCacheEntry //pssmsg中映射到expiry、cache以确定是否删除msg的唯一字段的校验和 120 fwdCacheMu sync.RWMutex 121 cacheTTL time.Duration //在fwdcache中保留消息的时间(未实现) 122 msgTTL time.Duration 123 paddingByteSize int 124 capstring string 125 outbox chan *PssMsg 126 127 //密钥与对等体 128 pubKeyPool map[string]map[Topic]*pssPeer //按主题将十六进制公钥映射到对等地址。 129 pubKeyPoolMu sync.RWMutex 130 symKeyPool map[string]map[Topic]*pssPeer //按主题将symkeyid映射到对等地址。 131 symKeyPoolMu sync.RWMutex 132 symKeyDecryptCache []*string //快速查找最近用于解密的符号键;最后使用的是堆栈顶部 133 symKeyDecryptCacheCursor int //指向上次使用的、包装在symkeydecryptcache数组上的模块化光标 134 symKeyDecryptCacheCapacity int //要保留的符号键的最大数量。 135 136 //消息处理 137 handlers map[Topic]map[*handler]bool //基于主题和版本的PSS有效负载处理程序。参见pss.handle()。 138 handlersMu sync.RWMutex 139 hashPool sync.Pool 140 topicHandlerCaps map[Topic]*handlerCaps //缓存每个主题处理程序的功能(请参见handlercap*types.go中的consts) 141 142 //过程 143 quitC chan struct{} 144 } 145 146 func (p *Pss) String() string { 147 return fmt.Sprintf("pss: addr %x, pubkey %v", p.BaseAddr(), common.ToHex(crypto.FromECDSAPub(&p.privateKey.PublicKey))) 148 } 149 150 //创建新的PSS实例。 151 // 152 //除了params,它还需要一个集群网络kademlia 153 //以及用于消息缓存存储的文件存储。 154 func NewPss(k *network.Kademlia, params *PssParams) (*Pss, error) { 155 if params.privateKey == nil { 156 return nil, errors.New("missing private key for pss") 157 } 158 cap := p2p.Cap{ 159 Name: pssProtocolName, 160 Version: pssVersion, 161 } 162 ps := &Pss{ 163 Kademlia: k, 164 privateKey: params.privateKey, 165 w: whisper.New(&whisper.DefaultConfig), 166 quitC: make(chan struct{}), 167 168 fwdPool: make(map[string]*protocols.Peer), 169 fwdCache: make(map[pssDigest]pssCacheEntry), 170 cacheTTL: params.CacheTTL, 171 msgTTL: params.MsgTTL, 172 paddingByteSize: defaultPaddingByteSize, 173 capstring: cap.String(), 174 outbox: make(chan *PssMsg, defaultOutboxCapacity), 175 176 pubKeyPool: make(map[string]map[Topic]*pssPeer), 177 symKeyPool: make(map[string]map[Topic]*pssPeer), 178 symKeyDecryptCache: make([]*string, params.SymKeyCacheCapacity), 179 symKeyDecryptCacheCapacity: params.SymKeyCacheCapacity, 180 181 handlers: make(map[Topic]map[*handler]bool), 182 topicHandlerCaps: make(map[Topic]*handlerCaps), 183 184 hashPool: sync.Pool{ 185 New: func() interface{} { 186 return sha3.NewLegacyKeccak256() 187 }, 188 }, 189 } 190 191 for i := 0; i < hasherCount; i++ { 192 hashfunc := storage.MakeHashFunc(storage.DefaultHash)() 193 ps.hashPool.Put(hashfunc) 194 } 195 196 return ps, nil 197 } 198 199 //////////////////////////////////////////////// 200 //章节:节点、服务接口 201 //////////////////////////////////////////////// 202 203 func (p *Pss) Start(srv *p2p.Server) error { 204 go func() { 205 ticker := time.NewTicker(defaultCleanInterval) 206 cacheTicker := time.NewTicker(p.cacheTTL) 207 defer ticker.Stop() 208 defer cacheTicker.Stop() 209 for { 210 select { 211 case <-cacheTicker.C: 212 p.cleanFwdCache() 213 case <-ticker.C: 214 p.cleanKeys() 215 case <-p.quitC: 216 return 217 } 218 } 219 }() 220 go func() { 221 for { 222 select { 223 case msg := <-p.outbox: 224 err := p.forward(msg) 225 if err != nil { 226 log.Error(err.Error()) 227 metrics.GetOrRegisterCounter("pss.forward.err", nil).Inc(1) 228 } 229 case <-p.quitC: 230 return 231 } 232 } 233 }() 234 log.Info("Started Pss") 235 log.Info("Loaded EC keys", "pubkey", common.ToHex(crypto.FromECDSAPub(p.PublicKey())), "secp256", common.ToHex(crypto.CompressPubkey(p.PublicKey()))) 236 return nil 237 } 238 239 func (p *Pss) Stop() error { 240 log.Info("Pss shutting down") 241 close(p.quitC) 242 return nil 243 } 244 245 var pssSpec = &protocols.Spec{ 246 Name: pssProtocolName, 247 Version: pssVersion, 248 MaxMsgSize: defaultMaxMsgSize, 249 Messages: []interface{}{ 250 PssMsg{}, 251 }, 252 } 253 254 func (p *Pss) Protocols() []p2p.Protocol { 255 return []p2p.Protocol{ 256 { 257 Name: pssSpec.Name, 258 Version: pssSpec.Version, 259 Length: pssSpec.Length(), 260 Run: p.Run, 261 }, 262 } 263 } 264 265 func (p *Pss) Run(peer *p2p.Peer, rw p2p.MsgReadWriter) error { 266 pp := protocols.NewPeer(peer, rw, pssSpec) 267 p.fwdPoolMu.Lock() 268 p.fwdPool[peer.Info().ID] = pp 269 p.fwdPoolMu.Unlock() 270 return pp.Run(p.handlePssMsg) 271 } 272 273 func (p *Pss) APIs() []rpc.API { 274 apis := []rpc.API{ 275 { 276 Namespace: "pss", 277 Version: "1.0", 278 Service: NewAPI(p), 279 Public: true, 280 }, 281 } 282 apis = append(apis, p.auxAPIs...) 283 return apis 284 } 285 286 //向PSS API添加API方法 287 //必须在节点启动之前运行 288 func (p *Pss) addAPI(api rpc.API) { 289 p.auxAPIs = append(p.auxAPIs, api) 290 } 291 292 //返回PSS节点的Swarm Kademlia地址 293 func (p *Pss) BaseAddr() []byte { 294 return p.Kademlia.BaseAddr() 295 } 296 297 //返回PSS节点的公钥 298 func (p *Pss) PublicKey() *ecdsa.PublicKey { 299 return &p.privateKey.PublicKey 300 } 301 302 //////////////////////////////////////////////// 303 //部分:消息处理 304 //////////////////////////////////////////////// 305 306 //将处理程序函数链接到主题 307 // 308 //信封主题与 309 //指定的主题将传递给给定的处理程序函数。 310 // 311 //每个主题可能有任意数量的处理程序函数。 312 // 313 //返回需要调用的注销函数 314 //注销处理程序, 315 func (p *Pss) Register(topic *Topic, hndlr *handler) func() { 316 p.handlersMu.Lock() 317 defer p.handlersMu.Unlock() 318 handlers := p.handlers[*topic] 319 if handlers == nil { 320 handlers = make(map[*handler]bool) 321 p.handlers[*topic] = handlers 322 log.Debug("registered handler", "caps", hndlr.caps) 323 } 324 if hndlr.caps == nil { 325 hndlr.caps = &handlerCaps{} 326 } 327 handlers[hndlr] = true 328 if _, ok := p.topicHandlerCaps[*topic]; !ok { 329 p.topicHandlerCaps[*topic] = &handlerCaps{} 330 } 331 if hndlr.caps.raw { 332 p.topicHandlerCaps[*topic].raw = true 333 } 334 if hndlr.caps.prox { 335 p.topicHandlerCaps[*topic].prox = true 336 } 337 return func() { p.deregister(topic, hndlr) } 338 } 339 func (p *Pss) deregister(topic *Topic, hndlr *handler) { 340 p.handlersMu.Lock() 341 defer p.handlersMu.Unlock() 342 handlers := p.handlers[*topic] 343 if len(handlers) > 1 { 344 delete(p.handlers, *topic) 345 //既然处理程序不在,主题帽可能已经更改。 346 caps := &handlerCaps{} 347 for h := range handlers { 348 if h.caps.raw { 349 caps.raw = true 350 } 351 if h.caps.prox { 352 caps.prox = true 353 } 354 } 355 p.topicHandlerCaps[*topic] = caps 356 return 357 } 358 delete(handlers, hndlr) 359 } 360 361 //获取各自主题的所有已注册处理程序 362 func (p *Pss) getHandlers(topic Topic) map[*handler]bool { 363 p.handlersMu.RLock() 364 defer p.handlersMu.RUnlock() 365 return p.handlers[topic] 366 } 367 368 //筛选要处理或转发的传入邮件。 369 //检查地址是否部分匹配 370 //如果是的话,它可以是我们的,我们处理它 371 //仅当有效负载无效时才会将错误传递给PSS协议处理程序PSSMSG 372 func (p *Pss) handlePssMsg(ctx context.Context, msg interface{}) error { 373 metrics.GetOrRegisterCounter("pss.handlepssmsg", nil).Inc(1) 374 pssmsg, ok := msg.(*PssMsg) 375 if !ok { 376 return fmt.Errorf("invalid message type. Expected *PssMsg, got %T ", msg) 377 } 378 log.Trace("handler", "self", label(p.Kademlia.BaseAddr()), "topic", label(pssmsg.Payload.Topic[:])) 379 if int64(pssmsg.Expire) < time.Now().Unix() { 380 metrics.GetOrRegisterCounter("pss.expire", nil).Inc(1) 381 log.Warn("pss filtered expired message", "from", common.ToHex(p.Kademlia.BaseAddr()), "to", common.ToHex(pssmsg.To)) 382 return nil 383 } 384 if p.checkFwdCache(pssmsg) { 385 log.Trace("pss relay block-cache match (process)", "from", common.ToHex(p.Kademlia.BaseAddr()), "to", (common.ToHex(pssmsg.To))) 386 return nil 387 } 388 p.addFwdCache(pssmsg) 389 390 psstopic := Topic(pssmsg.Payload.Topic) 391 392 //raw是要检查的最简单的处理程序意外事件,因此请首先检查 393 var isRaw bool 394 if pssmsg.isRaw() { 395 if _, ok := p.topicHandlerCaps[psstopic]; ok { 396 if !p.topicHandlerCaps[psstopic].raw { 397 log.Debug("No handler for raw message", "topic", psstopic) 398 return nil 399 } 400 } 401 isRaw = true 402 } 403 404 //检查我们是否可以成为收件人: 405 //-消息和部分地址上没有代理处理程序匹配 406 //-消息上的代理处理程序,并且无论部分地址是否匹配,我们都在代理中 407 //存储此结果,这样我们就不会对每个处理程序重新计算 408 var isProx bool 409 if _, ok := p.topicHandlerCaps[psstopic]; ok { 410 isProx = p.topicHandlerCaps[psstopic].prox 411 } 412 isRecipient := p.isSelfPossibleRecipient(pssmsg, isProx) 413 if !isRecipient { 414 log.Trace("pss was for someone else :'( ... forwarding", "pss", common.ToHex(p.BaseAddr()), "prox", isProx) 415 return p.enqueue(pssmsg) 416 } 417 418 log.Trace("pss for us, yay! ... let's process!", "pss", common.ToHex(p.BaseAddr()), "prox", isProx, "raw", isRaw, "topic", label(pssmsg.Payload.Topic[:])) 419 if err := p.process(pssmsg, isRaw, isProx); err != nil { 420 qerr := p.enqueue(pssmsg) 421 if qerr != nil { 422 return fmt.Errorf("process fail: processerr %v, queueerr: %v", err, qerr) 423 } 424 } 425 return nil 426 427 } 428 429 //入口点,用于处理当前节点可以作为目标收件人的消息。 430 //尝试使用存储的密钥进行对称和非对称解密。 431 //将消息发送到与消息主题匹配的所有处理程序 432 func (p *Pss) process(pssmsg *PssMsg, raw bool, prox bool) error { 433 metrics.GetOrRegisterCounter("pss.process", nil).Inc(1) 434 435 var err error 436 var recvmsg *whisper.ReceivedMessage 437 var payload []byte 438 var from PssAddress 439 var asymmetric bool 440 var keyid string 441 var keyFunc func(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, PssAddress, error) 442 443 envelope := pssmsg.Payload 444 psstopic := Topic(envelope.Topic) 445 446 if raw { 447 payload = pssmsg.Payload.Data 448 } else { 449 if pssmsg.isSym() { 450 keyFunc = p.processSym 451 } else { 452 asymmetric = true 453 keyFunc = p.processAsym 454 } 455 456 recvmsg, keyid, from, err = keyFunc(envelope) 457 if err != nil { 458 return errors.New("Decryption failed") 459 } 460 payload = recvmsg.Payload 461 } 462 463 if len(pssmsg.To) < addressLength { 464 if err := p.enqueue(pssmsg); err != nil { 465 return err 466 } 467 } 468 p.executeHandlers(psstopic, payload, from, raw, prox, asymmetric, keyid) 469 470 return nil 471 472 } 473 474 func (p *Pss) executeHandlers(topic Topic, payload []byte, from PssAddress, raw bool, prox bool, asymmetric bool, keyid string) { 475 handlers := p.getHandlers(topic) 476 peer := p2p.NewPeer(enode.ID{}, fmt.Sprintf("%x", from), []p2p.Cap{}) 477 for h := range handlers { 478 if !h.caps.raw && raw { 479 log.Warn("norawhandler") 480 continue 481 } 482 if !h.caps.prox && prox { 483 log.Warn("noproxhandler") 484 continue 485 } 486 err := (h.f)(payload, peer, asymmetric, keyid) 487 if err != nil { 488 log.Warn("Pss handler failed", "err", err) 489 } 490 } 491 } 492 493 //如果使用部分地址,将返回false 494 func (p *Pss) isSelfRecipient(msg *PssMsg) bool { 495 return bytes.Equal(msg.To, p.Kademlia.BaseAddr()) 496 } 497 498 //测试给定消息中最左边的字节与节点的kademlia地址的匹配 499 func (p *Pss) isSelfPossibleRecipient(msg *PssMsg, prox bool) bool { 500 local := p.Kademlia.BaseAddr() 501 502 //如果部分地址匹配,无论代理服务器是什么,我们都是可能的收件人。 503 //如果没有,并且没有设置代理,我们肯定没有 504 if bytes.Equal(msg.To, local[:len(msg.To)]) { 505 506 return true 507 } else if !prox { 508 return false 509 } 510 511 depth := p.Kademlia.NeighbourhoodDepth() 512 po, _ := network.Pof(p.Kademlia.BaseAddr(), msg.To, 0) 513 log.Trace("selfpossible", "po", po, "depth", depth) 514 515 return depth <= po 516 } 517 518 //////////////////////////////////////////////// 519 //部分:加密 520 //////////////////////////////////////////////// 521 522 //将对等ECDSA公钥链接到主题 523 // 524 //这对于非对称消息交换是必需的 525 //关于给定主题 526 // 527 //“address”中的值将用作 528 //公钥/主题关联 529 func (p *Pss) SetPeerPublicKey(pubkey *ecdsa.PublicKey, topic Topic, address PssAddress) error { 530 if err := validateAddress(address); err != nil { 531 return err 532 } 533 pubkeybytes := crypto.FromECDSAPub(pubkey) 534 if len(pubkeybytes) == 0 { 535 return fmt.Errorf("invalid public key: %v", pubkey) 536 } 537 pubkeyid := common.ToHex(pubkeybytes) 538 psp := &pssPeer{ 539 address: address, 540 } 541 p.pubKeyPoolMu.Lock() 542 if _, ok := p.pubKeyPool[pubkeyid]; !ok { 543 p.pubKeyPool[pubkeyid] = make(map[Topic]*pssPeer) 544 } 545 p.pubKeyPool[pubkeyid][topic] = psp 546 p.pubKeyPoolMu.Unlock() 547 log.Trace("added pubkey", "pubkeyid", pubkeyid, "topic", topic, "address", address) 548 return nil 549 } 550 551 //自动为主题和地址提示生成新的symkey 552 func (p *Pss) GenerateSymmetricKey(topic Topic, address PssAddress, addToCache bool) (string, error) { 553 keyid, err := p.w.GenerateSymKey() 554 if err != nil { 555 return "", err 556 } 557 p.addSymmetricKeyToPool(keyid, topic, address, addToCache, false) 558 return keyid, nil 559 } 560 561 //将对等对称密钥(任意字节序列)链接到主题 562 // 563 //这是对称加密邮件交换所必需的 564 //关于给定主题 565 // 566 //密钥存储在Whisper后端。 567 // 568 //如果addtocache设置为true,则密钥将添加到密钥的缓存中。 569 //用于尝试对传入消息进行对称解密。 570 // 571 //返回可用于检索键字节的字符串ID 572 //从Whisper后端(请参阅pss.getSymmetricKey()) 573 func (p *Pss) SetSymmetricKey(key []byte, topic Topic, address PssAddress, addtocache bool) (string, error) { 574 if err := validateAddress(address); err != nil { 575 return "", err 576 } 577 return p.setSymmetricKey(key, topic, address, addtocache, true) 578 } 579 580 func (p *Pss) setSymmetricKey(key []byte, topic Topic, address PssAddress, addtocache bool, protected bool) (string, error) { 581 keyid, err := p.w.AddSymKeyDirect(key) 582 if err != nil { 583 return "", err 584 } 585 p.addSymmetricKeyToPool(keyid, topic, address, addtocache, protected) 586 return keyid, nil 587 } 588 589 //向PSS密钥池添加对称密钥,并可以选择添加密钥 590 //用于尝试对称解密的密钥集合 591 //传入消息 592 func (p *Pss) addSymmetricKeyToPool(keyid string, topic Topic, address PssAddress, addtocache bool, protected bool) { 593 psp := &pssPeer{ 594 address: address, 595 protected: protected, 596 } 597 p.symKeyPoolMu.Lock() 598 if _, ok := p.symKeyPool[keyid]; !ok { 599 p.symKeyPool[keyid] = make(map[Topic]*pssPeer) 600 } 601 p.symKeyPool[keyid][topic] = psp 602 p.symKeyPoolMu.Unlock() 603 if addtocache { 604 p.symKeyDecryptCacheCursor++ 605 p.symKeyDecryptCache[p.symKeyDecryptCacheCursor%cap(p.symKeyDecryptCache)] = &keyid 606 } 607 key, _ := p.GetSymmetricKey(keyid) 608 log.Trace("added symkey", "symkeyid", keyid, "symkey", common.ToHex(key), "topic", topic, "address", address, "cache", addtocache) 609 } 610 611 //返回存储在Whisper后端中的对称密钥字节seqyence 612 //通过其唯一ID 613 // 614 //从Whisper后端传递错误值 615 func (p *Pss) GetSymmetricKey(symkeyid string) ([]byte, error) { 616 symkey, err := p.w.GetSymKey(symkeyid) 617 if err != nil { 618 return nil, err 619 } 620 return symkey, nil 621 } 622 623 //返回特定公钥的所有录制主题和地址组合 624 func (p *Pss) GetPublickeyPeers(keyid string) (topic []Topic, address []PssAddress, err error) { 625 p.pubKeyPoolMu.RLock() 626 defer p.pubKeyPoolMu.RUnlock() 627 for t, peer := range p.pubKeyPool[keyid] { 628 topic = append(topic, t) 629 address = append(address, peer.address) 630 } 631 632 return topic, address, nil 633 } 634 635 func (p *Pss) getPeerAddress(keyid string, topic Topic) (PssAddress, error) { 636 p.pubKeyPoolMu.RLock() 637 defer p.pubKeyPoolMu.RUnlock() 638 if peers, ok := p.pubKeyPool[keyid]; ok { 639 if t, ok := peers[topic]; ok { 640 return t.address, nil 641 } 642 } 643 return nil, fmt.Errorf("peer with pubkey %s, topic %x not found", keyid, topic) 644 } 645 646 //尝试解密、验证和解包 647 //对称加密消息 648 //如果成功,则返回解包的Whisper ReceivedMessage结构 649 //封装解密的消息和Whisper后端ID 650 //用于解密消息的对称密钥。 651 //如果解密消息失败或消息已损坏,则失败。 652 func (p *Pss) processSym(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, PssAddress, error) { 653 metrics.GetOrRegisterCounter("pss.process.sym", nil).Inc(1) 654 655 for i := p.symKeyDecryptCacheCursor; i > p.symKeyDecryptCacheCursor-cap(p.symKeyDecryptCache) && i > 0; i-- { 656 symkeyid := p.symKeyDecryptCache[i%cap(p.symKeyDecryptCache)] 657 symkey, err := p.w.GetSymKey(*symkeyid) 658 if err != nil { 659 continue 660 } 661 recvmsg, err := envelope.OpenSymmetric(symkey) 662 if err != nil { 663 continue 664 } 665 if !recvmsg.Validate() { 666 return nil, "", nil, fmt.Errorf("symmetrically encrypted message has invalid signature or is corrupt") 667 } 668 p.symKeyPoolMu.Lock() 669 from := p.symKeyPool[*symkeyid][Topic(envelope.Topic)].address 670 p.symKeyPoolMu.Unlock() 671 p.symKeyDecryptCacheCursor++ 672 p.symKeyDecryptCache[p.symKeyDecryptCacheCursor%cap(p.symKeyDecryptCache)] = symkeyid 673 return recvmsg, *symkeyid, from, nil 674 } 675 return nil, "", nil, fmt.Errorf("could not decrypt message") 676 } 677 678 //尝试解密、验证和解包 679 //非对称加密消息 680 //如果成功,则返回解包的Whisper ReceivedMessage结构 681 //封装解密的消息,以及 682 //用于解密消息的公钥。 683 //如果解密消息失败或消息已损坏,则失败。 684 func (p *Pss) processAsym(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, PssAddress, error) { 685 metrics.GetOrRegisterCounter("pss.process.asym", nil).Inc(1) 686 687 recvmsg, err := envelope.OpenAsymmetric(p.privateKey) 688 if err != nil { 689 return nil, "", nil, fmt.Errorf("could not decrypt message: %s", err) 690 } 691 //检查签名(如果有签名),去掉填充 692 if !recvmsg.Validate() { 693 return nil, "", nil, fmt.Errorf("invalid message") 694 } 695 pubkeyid := common.ToHex(crypto.FromECDSAPub(recvmsg.Src)) 696 var from PssAddress 697 p.pubKeyPoolMu.Lock() 698 if p.pubKeyPool[pubkeyid][Topic(envelope.Topic)] != nil { 699 from = p.pubKeyPool[pubkeyid][Topic(envelope.Topic)].address 700 } 701 p.pubKeyPoolMu.Unlock() 702 return recvmsg, pubkeyid, from, nil 703 } 704 705 //symkey垃圾收集 706 //如果出现以下情况,钥匙将被取下: 707 //-未标记为受保护 708 //-不在传入解密缓存中 709 func (p *Pss) cleanKeys() (count int) { 710 for keyid, peertopics := range p.symKeyPool { 711 var expiredtopics []Topic 712 for topic, psp := range peertopics { 713 if psp.protected { 714 continue 715 } 716 717 var match bool 718 for i := p.symKeyDecryptCacheCursor; i > p.symKeyDecryptCacheCursor-cap(p.symKeyDecryptCache) && i > 0; i-- { 719 cacheid := p.symKeyDecryptCache[i%cap(p.symKeyDecryptCache)] 720 if *cacheid == keyid { 721 match = true 722 } 723 } 724 if !match { 725 expiredtopics = append(expiredtopics, topic) 726 } 727 } 728 for _, topic := range expiredtopics { 729 p.symKeyPoolMu.Lock() 730 delete(p.symKeyPool[keyid], topic) 731 log.Trace("symkey cleanup deletion", "symkeyid", keyid, "topic", topic, "val", p.symKeyPool[keyid]) 732 p.symKeyPoolMu.Unlock() 733 count++ 734 } 735 } 736 return 737 } 738 739 //////////////////////////////////////////////// 740 //部分:消息发送 741 //////////////////////////////////////////////// 742 743 func (p *Pss) enqueue(msg *PssMsg) error { 744 select { 745 case p.outbox <- msg: 746 return nil 747 default: 748 } 749 750 metrics.GetOrRegisterCounter("pss.enqueue.outbox.full", nil).Inc(1) 751 return errors.New("outbox full") 752 } 753 754 //发送原始消息(任何加密都由调用客户端负责) 755 // 756 //如果不允许原始消息,将失败 757 func (p *Pss) SendRaw(address PssAddress, topic Topic, msg []byte) error { 758 if err := validateAddress(address); err != nil { 759 return err 760 } 761 pssMsgParams := &msgParams{ 762 raw: true, 763 } 764 payload := &whisper.Envelope{ 765 Data: msg, 766 Topic: whisper.TopicType(topic), 767 } 768 pssMsg := newPssMsg(pssMsgParams) 769 pssMsg.To = address 770 pssMsg.Expire = uint32(time.Now().Add(p.msgTTL).Unix()) 771 pssMsg.Payload = payload 772 p.addFwdCache(pssMsg) 773 err := p.enqueue(pssMsg) 774 if err != nil { 775 return err 776 } 777 778 //如果我们有关于这个主题的代理处理程序 779 //同时向我们自己传递信息 780 if _, ok := p.topicHandlerCaps[topic]; ok { 781 if p.isSelfPossibleRecipient(pssMsg, true) && p.topicHandlerCaps[topic].prox { 782 return p.process(pssMsg, true, true) 783 } 784 } 785 return nil 786 } 787 788 //使用对称加密发送消息 789 // 790 //如果密钥ID与任何存储的对称密钥不匹配,则失败 791 func (p *Pss) SendSym(symkeyid string, topic Topic, msg []byte) error { 792 symkey, err := p.GetSymmetricKey(symkeyid) 793 if err != nil { 794 return fmt.Errorf("missing valid send symkey %s: %v", symkeyid, err) 795 } 796 p.symKeyPoolMu.Lock() 797 psp, ok := p.symKeyPool[symkeyid][topic] 798 p.symKeyPoolMu.Unlock() 799 if !ok { 800 return fmt.Errorf("invalid topic '%s' for symkey '%s'", topic.String(), symkeyid) 801 } 802 return p.send(psp.address, topic, msg, false, symkey) 803 } 804 805 //使用非对称加密发送消息 806 // 807 //如果密钥ID与存储的公钥中的任何一个不匹配,则失败 808 func (p *Pss) SendAsym(pubkeyid string, topic Topic, msg []byte) error { 809 if _, err := crypto.UnmarshalPubkey(common.FromHex(pubkeyid)); err != nil { 810 return fmt.Errorf("Cannot unmarshal pubkey: %x", pubkeyid) 811 } 812 p.pubKeyPoolMu.Lock() 813 psp, ok := p.pubKeyPool[pubkeyid][topic] 814 p.pubKeyPoolMu.Unlock() 815 if !ok { 816 return fmt.Errorf("invalid topic '%s' for pubkey '%s'", topic.String(), pubkeyid) 817 } 818 return p.send(psp.address, topic, msg, true, common.FromHex(pubkeyid)) 819 } 820 821 //send不区分有效负载,并将接受任何字节片作为有效负载 822 //它为指定的收件人和主题生成一个耳语信封, 823 //并将消息有效负载包装在其中。 824 //TODO:实现正确的消息填充 825 func (p *Pss) send(to []byte, topic Topic, msg []byte, asymmetric bool, key []byte) error { 826 metrics.GetOrRegisterCounter("pss.send", nil).Inc(1) 827 828 if key == nil || bytes.Equal(key, []byte{}) { 829 return fmt.Errorf("Zero length key passed to pss send") 830 } 831 padding := make([]byte, p.paddingByteSize) 832 c, err := rand.Read(padding) 833 if err != nil { 834 return err 835 } else if c < p.paddingByteSize { 836 return fmt.Errorf("invalid padding length: %d", c) 837 } 838 wparams := &whisper.MessageParams{ 839 TTL: defaultWhisperTTL, 840 Src: p.privateKey, 841 Topic: whisper.TopicType(topic), 842 WorkTime: defaultWhisperWorkTime, 843 PoW: defaultWhisperPoW, 844 Payload: msg, 845 Padding: padding, 846 } 847 if asymmetric { 848 pk, err := crypto.UnmarshalPubkey(key) 849 if err != nil { 850 return fmt.Errorf("Cannot unmarshal pubkey: %x", key) 851 } 852 wparams.Dst = pk 853 } else { 854 wparams.KeySym = key 855 } 856 //设置传出消息容器,该容器执行加密和信封包装 857 woutmsg, err := whisper.NewSentMessage(wparams) 858 if err != nil { 859 return fmt.Errorf("failed to generate whisper message encapsulation: %v", err) 860 } 861 //执行加密。 862 //由于设置难度很低,无法执行/执行可忽略的POW 863 //之后,消息就可以发送了 864 envelope, err := woutmsg.Wrap(wparams) 865 if err != nil { 866 return fmt.Errorf("failed to perform whisper encryption: %v", err) 867 } 868 log.Trace("pssmsg whisper done", "env", envelope, "wparams payload", common.ToHex(wparams.Payload), "to", common.ToHex(to), "asym", asymmetric, "key", common.ToHex(key)) 869 870 //准备DEVP2P传输 871 pssMsgParams := &msgParams{ 872 sym: !asymmetric, 873 } 874 pssMsg := newPssMsg(pssMsgParams) 875 pssMsg.To = to 876 pssMsg.Expire = uint32(time.Now().Add(p.msgTTL).Unix()) 877 pssMsg.Payload = envelope 878 err = p.enqueue(pssMsg) 879 if err != nil { 880 return err 881 } 882 if _, ok := p.topicHandlerCaps[topic]; ok { 883 if p.isSelfPossibleRecipient(pssMsg, true) && p.topicHandlerCaps[topic].prox { 884 return p.process(pssMsg, true, true) 885 } 886 } 887 return nil 888 } 889 890 //sendfunc是一个帮助函数,它尝试发送消息并在成功时返回true。 891 //它在这里设置为在生产中使用,并在测试中可选地重写。 892 var sendFunc func(p *Pss, sp *network.Peer, msg *PssMsg) bool = sendMsg 893 894 //尝试发送消息,如果成功则返回true 895 func sendMsg(p *Pss, sp *network.Peer, msg *PssMsg) bool { 896 var isPssEnabled bool 897 info := sp.Info() 898 for _, capability := range info.Caps { 899 if capability == p.capstring { 900 isPssEnabled = true 901 break 902 } 903 } 904 if !isPssEnabled { 905 log.Error("peer doesn't have matching pss capabilities, skipping", "peer", info.Name, "caps", info.Caps) 906 return false 907 } 908 909 //从转发对等缓存获取协议对等 910 p.fwdPoolMu.RLock() 911 pp := p.fwdPool[sp.Info().ID] 912 p.fwdPoolMu.RUnlock() 913 914 err := pp.Send(context.TODO(), msg) 915 if err != nil { 916 metrics.GetOrRegisterCounter("pss.pp.send.error", nil).Inc(1) 917 log.Error(err.Error()) 918 } 919 920 return err == nil 921 } 922 923 //根据算法,将基于收件人地址的PSS消息转发给对等方 924 //如下所述。收件人地址可以是任意长度,字节片将匹配 925 //等效长度的对等地址的MSB切片。 926 // 927 //如果收件人地址(或部分地址)在转发的邻近深度内 928 //节点,然后它将被转发到转发节点的所有最近邻居。万一 929 //部分地址,如果存在,则应转发给与部分地址匹配的所有对等方 930 //是任意的;否则仅限于最接近收件人地址的一个对等机。在任何情况下,如果 931 //转发失败,节点应尝试将其转发到下一个最佳对等端,直到消息 932 //已成功转发到至少一个对等机。 933 func (p *Pss) forward(msg *PssMsg) error { 934 metrics.GetOrRegisterCounter("pss.forward", nil).Inc(1) 935 sent := 0 //成功发送的次数 936 to := make([]byte, addressLength) 937 copy(to[:len(msg.To)], msg.To) 938 neighbourhoodDepth := p.Kademlia.NeighbourhoodDepth() 939 940 //光明与黑暗是对立的。从地址中删除的字节越多,越黑, 941 //但是亮度变小了。这里亮度等于目的地址中给定的位数。 942 luminosityRadius := len(msg.To) * 8 943 944 //接近顺序功能匹配到邻接位(po<=neighbourhooddepth) 945 pof := pot.DefaultPof(neighbourhoodDepth) 946 947 //消息广播软阈值 948 broadcastThreshold, _ := pof(to, p.BaseAddr(), 0) 949 if broadcastThreshold > luminosityRadius { 950 broadcastThreshold = luminosityRadius 951 } 952 953 var onlySendOnce bool //指示是否只应将消息发送到一个地址最近的对等机 954 955 //如果从收件人地址而不是基地址测量(参见kademlia.eachconn 956 //呼叫下面),然后将出现与收件人地址位于同一个近箱中的对等机。 957 //[至少]靠近一位,但只有在收件人地址中给出这些附加位时。 958 if broadcastThreshold < luminosityRadius && broadcastThreshold < neighbourhoodDepth { 959 broadcastThreshold++ 960 onlySendOnce = true 961 } 962 963 p.Kademlia.EachConn(to, addressLength*8, func(sp *network.Peer, po int) bool { 964 if po < broadcastThreshold && sent > 0 { 965 return false //停止迭代 966 } 967 if sendFunc(p, sp, msg) { 968 sent++ 969 if onlySendOnce { 970 return false 971 } 972 if po == addressLength*8 { 973 //如果成功发送到确切的收件人,则停止迭代(完全匹配完整地址) 974 return false 975 } 976 } 977 return true 978 }) 979 980 //如果发送失败,请在发送队列中重新插入消息 981 if sent == 0 { 982 log.Debug("unable to forward to any peers") 983 if err := p.enqueue(msg); err != nil { 984 metrics.GetOrRegisterCounter("pss.forward.enqueue.error", nil).Inc(1) 985 log.Error(err.Error()) 986 return err 987 } 988 } 989 990 //缓存消息 991 p.addFwdCache(msg) 992 return nil 993 } 994 995 //////////////////////////////////////////////// 996 //部分:缓存 997 //////////////////////////////////////////////// 998 999 //cleanfwdcache用于定期从转发缓存中删除过期条目。 1000 func (p *Pss) cleanFwdCache() { 1001 metrics.GetOrRegisterCounter("pss.cleanfwdcache", nil).Inc(1) 1002 p.fwdCacheMu.Lock() 1003 defer p.fwdCacheMu.Unlock() 1004 for k, v := range p.fwdCache { 1005 if v.expiresAt.Before(time.Now()) { 1006 delete(p.fwdCache, k) 1007 } 1008 } 1009 } 1010 1011 func label(b []byte) string { 1012 return fmt.Sprintf("%04x", b[:2]) 1013 } 1014 1015 //向缓存中添加消息 1016 func (p *Pss) addFwdCache(msg *PssMsg) error { 1017 metrics.GetOrRegisterCounter("pss.addfwdcache", nil).Inc(1) 1018 1019 var entry pssCacheEntry 1020 var ok bool 1021 1022 p.fwdCacheMu.Lock() 1023 defer p.fwdCacheMu.Unlock() 1024 1025 digest := p.digest(msg) 1026 if entry, ok = p.fwdCache[digest]; !ok { 1027 entry = pssCacheEntry{} 1028 } 1029 entry.expiresAt = time.Now().Add(p.cacheTTL) 1030 p.fwdCache[digest] = entry 1031 return nil 1032 } 1033 1034 //检查消息是否在缓存中 1035 func (p *Pss) checkFwdCache(msg *PssMsg) bool { 1036 p.fwdCacheMu.Lock() 1037 defer p.fwdCacheMu.Unlock() 1038 1039 digest := p.digest(msg) 1040 entry, ok := p.fwdCache[digest] 1041 if ok { 1042 if entry.expiresAt.After(time.Now()) { 1043 log.Trace("unexpired cache", "digest", fmt.Sprintf("%x", digest)) 1044 metrics.GetOrRegisterCounter("pss.checkfwdcache.unexpired", nil).Inc(1) 1045 return true 1046 } 1047 metrics.GetOrRegisterCounter("pss.checkfwdcache.expired", nil).Inc(1) 1048 } 1049 return false 1050 } 1051 1052 //消息摘要 1053 func (p *Pss) digest(msg *PssMsg) pssDigest { 1054 return p.digestBytes(msg.serialize()) 1055 } 1056 1057 func (p *Pss) digestBytes(msg []byte) pssDigest { 1058 hasher := p.hashPool.Get().(hash.Hash) 1059 defer p.hashPool.Put(hasher) 1060 hasher.Reset() 1061 hasher.Write(msg) 1062 digest := pssDigest{} 1063 key := hasher.Sum(nil) 1064 copy(digest[:], key[:digestLength]) 1065 return digest 1066 } 1067 1068 func validateAddress(addr PssAddress) error { 1069 if len(addr) > addressLength { 1070 return errors.New("address too long") 1071 } 1072 return nil 1073 } 1074