github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/pss/protocol.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 // 26 27 package pss 28 29 import ( 30 "bytes" 31 "fmt" 32 "sync" 33 "time" 34 35 "github.com/ethereum/go-ethereum/p2p" 36 "github.com/ethereum/go-ethereum/p2p/protocols" 37 "github.com/ethereum/go-ethereum/rlp" 38 "github.com/ethereum/go-ethereum/swarm/log" 39 ) 40 41 const ( 42 IsActiveProtocol = true 43 ) 44 45 // 46 type ProtocolMsg struct { 47 Code uint64 48 Size uint32 49 Payload []byte 50 ReceivedAt time.Time 51 } 52 53 // 54 func NewProtocolMsg(code uint64, msg interface{}) ([]byte, error) { 55 56 rlpdata, err := rlp.EncodeToBytes(msg) 57 if err != nil { 58 return nil, err 59 } 60 61 // 62 smsg := &ProtocolMsg{ 63 Code: code, 64 Size: uint32(len(rlpdata)), 65 Payload: rlpdata, 66 } 67 68 return rlp.EncodeToBytes(smsg) 69 } 70 71 // 72 // 73 // 74 type ProtocolParams struct { 75 Asymmetric bool 76 Symmetric bool 77 } 78 79 // 80 // 81 // 82 type PssReadWriter struct { 83 *Pss 84 LastActive time.Time 85 rw chan p2p.Msg 86 spec *protocols.Spec 87 topic *Topic 88 sendFunc func(string, Topic, []byte) error 89 key string 90 closed bool 91 } 92 93 // 94 func (prw *PssReadWriter) ReadMsg() (p2p.Msg, error) { 95 msg := <-prw.rw 96 log.Trace(fmt.Sprintf("pssrw readmsg: %v", msg)) 97 return msg, nil 98 } 99 100 // 101 func (prw *PssReadWriter) WriteMsg(msg p2p.Msg) error { 102 log.Trace("pssrw writemsg", "msg", msg) 103 if prw.closed { 104 return fmt.Errorf("connection closed") 105 } 106 rlpdata := make([]byte, msg.Size) 107 msg.Payload.Read(rlpdata) 108 pmsg, err := rlp.EncodeToBytes(ProtocolMsg{ 109 Code: msg.Code, 110 Size: msg.Size, 111 Payload: rlpdata, 112 }) 113 if err != nil { 114 return err 115 } 116 return prw.sendFunc(prw.key, *prw.topic, pmsg) 117 } 118 119 // 120 func (prw *PssReadWriter) injectMsg(msg p2p.Msg) error { 121 log.Trace(fmt.Sprintf("pssrw injectmsg: %v", msg)) 122 prw.rw <- msg 123 return nil 124 } 125 126 // 127 type Protocol struct { 128 *Pss 129 proto *p2p.Protocol 130 topic *Topic 131 spec *protocols.Spec 132 pubKeyRWPool map[string]p2p.MsgReadWriter 133 symKeyRWPool map[string]p2p.MsgReadWriter 134 Asymmetric bool 135 Symmetric bool 136 RWPoolMu sync.Mutex 137 } 138 139 // 140 // 141 // 142 // 143 // 144 // 145 func RegisterProtocol(ps *Pss, topic *Topic, spec *protocols.Spec, targetprotocol *p2p.Protocol, options *ProtocolParams) (*Protocol, error) { 146 if !options.Asymmetric && !options.Symmetric { 147 return nil, fmt.Errorf("specify at least one of asymmetric or symmetric messaging mode") 148 } 149 pp := &Protocol{ 150 Pss: ps, 151 proto: targetprotocol, 152 topic: topic, 153 spec: spec, 154 pubKeyRWPool: make(map[string]p2p.MsgReadWriter), 155 symKeyRWPool: make(map[string]p2p.MsgReadWriter), 156 Asymmetric: options.Asymmetric, 157 Symmetric: options.Symmetric, 158 } 159 return pp, nil 160 } 161 162 // 163 // 164 // 165 // 166 // 167 // 168 // 169 // 170 // 171 // 172 // 173 func (p *Protocol) Handle(msg []byte, peer *p2p.Peer, asymmetric bool, keyid string) error { 174 var vrw *PssReadWriter 175 if p.Asymmetric != asymmetric && p.Symmetric == !asymmetric { 176 return fmt.Errorf("invalid protocol encryption") 177 } else if (!p.isActiveSymKey(keyid, *p.topic) && !asymmetric) || 178 (!p.isActiveAsymKey(keyid, *p.topic) && asymmetric) { 179 180 rw, err := p.AddPeer(peer, *p.topic, asymmetric, keyid) 181 if err != nil { 182 return err 183 } else if rw == nil { 184 return fmt.Errorf("handle called on nil MsgReadWriter for new key " + keyid) 185 } 186 vrw = rw.(*PssReadWriter) 187 } 188 189 pmsg, err := ToP2pMsg(msg) 190 if err != nil { 191 return fmt.Errorf("could not decode pssmsg") 192 } 193 if asymmetric { 194 if p.pubKeyRWPool[keyid] == nil { 195 return fmt.Errorf("handle called on nil MsgReadWriter for key " + keyid) 196 } 197 vrw = p.pubKeyRWPool[keyid].(*PssReadWriter) 198 } else { 199 if p.symKeyRWPool[keyid] == nil { 200 return fmt.Errorf("handle called on nil MsgReadWriter for key " + keyid) 201 } 202 vrw = p.symKeyRWPool[keyid].(*PssReadWriter) 203 } 204 vrw.injectMsg(pmsg) 205 return nil 206 } 207 208 // 209 func (p *Protocol) isActiveSymKey(key string, topic Topic) bool { 210 return p.symKeyRWPool[key] != nil 211 } 212 213 // 214 func (p *Protocol) isActiveAsymKey(key string, topic Topic) bool { 215 return p.pubKeyRWPool[key] != nil 216 } 217 218 // 219 func ToP2pMsg(msg []byte) (p2p.Msg, error) { 220 payload := &ProtocolMsg{} 221 if err := rlp.DecodeBytes(msg, payload); err != nil { 222 return p2p.Msg{}, fmt.Errorf("pss protocol handler unable to decode payload as p2p message: %v", err) 223 } 224 225 return p2p.Msg{ 226 Code: payload.Code, 227 Size: uint32(len(payload.Payload)), 228 ReceivedAt: time.Now(), 229 Payload: bytes.NewBuffer(payload.Payload), 230 }, nil 231 } 232 233 // 234 // 235 // 236 // 237 // 238 func (p *Protocol) AddPeer(peer *p2p.Peer, topic Topic, asymmetric bool, key string) (p2p.MsgReadWriter, error) { 239 rw := &PssReadWriter{ 240 Pss: p.Pss, 241 rw: make(chan p2p.Msg), 242 spec: p.spec, 243 topic: p.topic, 244 key: key, 245 } 246 if asymmetric { 247 rw.sendFunc = p.Pss.SendAsym 248 } else { 249 rw.sendFunc = p.Pss.SendSym 250 } 251 if asymmetric { 252 p.Pss.pubKeyPoolMu.Lock() 253 if _, ok := p.Pss.pubKeyPool[key]; !ok { 254 return nil, fmt.Errorf("asym key does not exist: %s", key) 255 } 256 p.Pss.pubKeyPoolMu.Unlock() 257 p.RWPoolMu.Lock() 258 p.pubKeyRWPool[key] = rw 259 p.RWPoolMu.Unlock() 260 } else { 261 p.Pss.symKeyPoolMu.Lock() 262 if _, ok := p.Pss.symKeyPool[key]; !ok { 263 return nil, fmt.Errorf("symkey does not exist: %s", key) 264 } 265 p.Pss.symKeyPoolMu.Unlock() 266 p.RWPoolMu.Lock() 267 p.symKeyRWPool[key] = rw 268 p.RWPoolMu.Unlock() 269 } 270 go func() { 271 err := p.proto.Run(peer, rw) 272 log.Warn(fmt.Sprintf("pss vprotocol quit on %v topic %v: %v", peer, topic, err)) 273 }() 274 return rw, nil 275 } 276 277 func (p *Protocol) RemovePeer(asymmetric bool, key string) { 278 log.Debug("closing pss peer", "asym", asymmetric, "key", key) 279 p.RWPoolMu.Lock() 280 defer p.RWPoolMu.Unlock() 281 if asymmetric { 282 rw := p.pubKeyRWPool[key].(*PssReadWriter) 283 rw.closed = true 284 delete(p.pubKeyRWPool, key) 285 } else { 286 rw := p.symKeyRWPool[key].(*PssReadWriter) 287 rw.closed = true 288 delete(p.symKeyRWPool, key) 289 } 290 } 291 292 // 293 func ProtocolTopic(spec *protocols.Spec) Topic { 294 return BytesToTopic([]byte(fmt.Sprintf("%s:%d", spec.Name, spec.Version))) 295 }