github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/pss/protocol.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 //</624450116886990848> 11 12 13 //+建设!NOPSS协议 14 15 package pss 16 17 import ( 18 "bytes" 19 "fmt" 20 "sync" 21 "time" 22 23 "github.com/ethereum/go-ethereum/p2p" 24 "github.com/ethereum/go-ethereum/p2p/protocols" 25 "github.com/ethereum/go-ethereum/rlp" 26 "github.com/ethereum/go-ethereum/swarm/log" 27 ) 28 29 const ( 30 IsActiveProtocol = true 31 ) 32 33 //用于通过PSS传输的devp2p协议消息的方便包装器 34 type ProtocolMsg struct { 35 Code uint64 36 Size uint32 37 Payload []byte 38 ReceivedAt time.Time 39 } 40 41 //创建protocolmsg 42 func NewProtocolMsg(code uint64, msg interface{}) ([]byte, error) { 43 44 rlpdata, err := rlp.EncodeToBytes(msg) 45 if err != nil { 46 return nil, err 47 } 48 49 //TODO验证嵌套结构不能在RLP中使用 50 smsg := &ProtocolMsg{ 51 Code: code, 52 Size: uint32(len(rlpdata)), 53 Payload: rlpdata, 54 } 55 56 return rlp.EncodeToBytes(smsg) 57 } 58 59 //要传递到新协议实例的协议选项 60 // 61 //参数指定允许哪些加密方案 62 type ProtocolParams struct { 63 Asymmetric bool 64 Symmetric bool 65 } 66 67 //PSSReadWriter用devp2p协议发送/接收桥接PSS发送/接收 68 // 69 //实现p2p.msgreadwriter 70 type PssReadWriter struct { 71 *Pss 72 LastActive time.Time 73 rw chan p2p.Msg 74 spec *protocols.Spec 75 topic *Topic 76 sendFunc func(string, Topic, []byte) error 77 key string 78 closed bool 79 } 80 81 //实现p2p.msgreader 82 func (prw *PssReadWriter) ReadMsg() (p2p.Msg, error) { 83 msg := <-prw.rw 84 log.Trace(fmt.Sprintf("pssrw readmsg: %v", msg)) 85 return msg, nil 86 } 87 88 //实现p2p.msgWriter 89 func (prw *PssReadWriter) WriteMsg(msg p2p.Msg) error { 90 log.Trace("pssrw writemsg", "msg", msg) 91 if prw.closed { 92 return fmt.Errorf("connection closed") 93 } 94 rlpdata := make([]byte, msg.Size) 95 msg.Payload.Read(rlpdata) 96 pmsg, err := rlp.EncodeToBytes(ProtocolMsg{ 97 Code: msg.Code, 98 Size: msg.Size, 99 Payload: rlpdata, 100 }) 101 if err != nil { 102 return err 103 } 104 return prw.sendFunc(prw.key, *prw.topic, pmsg) 105 } 106 107 //将p2p.msg注入msgreadwriter,使其出现在关联的p2p.msgreader上 108 func (prw *PssReadWriter) injectMsg(msg p2p.Msg) error { 109 log.Trace(fmt.Sprintf("pssrw injectmsg: %v", msg)) 110 prw.rw <- msg 111 return nil 112 } 113 114 //PSS上仿真devp2p的方便对象 115 type Protocol struct { 116 *Pss 117 proto *p2p.Protocol 118 topic *Topic 119 spec *protocols.Spec 120 pubKeyRWPool map[string]p2p.MsgReadWriter 121 symKeyRWPool map[string]p2p.MsgReadWriter 122 Asymmetric bool 123 Symmetric bool 124 RWPoolMu sync.Mutex 125 } 126 127 //在特定PSS主题上激活devp2p仿真 128 // 129 //必须指定一个或两个加密方案。如果 130 //只指定了一个,协议将无效 131 //对于另一个,并将使消息处理程序 132 //返回错误 133 func RegisterProtocol(ps *Pss, topic *Topic, spec *protocols.Spec, targetprotocol *p2p.Protocol, options *ProtocolParams) (*Protocol, error) { 134 if !options.Asymmetric && !options.Symmetric { 135 return nil, fmt.Errorf("specify at least one of asymmetric or symmetric messaging mode") 136 } 137 pp := &Protocol{ 138 Pss: ps, 139 proto: targetprotocol, 140 topic: topic, 141 spec: spec, 142 pubKeyRWPool: make(map[string]p2p.MsgReadWriter), 143 symKeyRWPool: make(map[string]p2p.MsgReadWriter), 144 Asymmetric: options.Asymmetric, 145 Symmetric: options.Symmetric, 146 } 147 return pp, nil 148 } 149 150 //通过devp2p仿真接收消息的通用处理程序 151 // 152 //将传递给pss.register()。 153 // 154 //将在新的传入对等机上运行协议,前提是 155 //消息的加密密钥在内部具有匹配项 156 //PSS密钥池 157 // 158 //如果协议对消息加密方案无效,则失败, 159 //如果添加新对等端失败,或者消息不是序列化的 160 //p2p.msg(如果它是从这个对象发送的,它将一直是这样)。 161 func (p *Protocol) Handle(msg []byte, peer *p2p.Peer, asymmetric bool, keyid string) error { 162 var vrw *PssReadWriter 163 if p.Asymmetric != asymmetric && p.Symmetric == !asymmetric { 164 return fmt.Errorf("invalid protocol encryption") 165 } else if (!p.isActiveSymKey(keyid, *p.topic) && !asymmetric) || 166 (!p.isActiveAsymKey(keyid, *p.topic) && asymmetric) { 167 168 rw, err := p.AddPeer(peer, *p.topic, asymmetric, keyid) 169 if err != nil { 170 return err 171 } else if rw == nil { 172 return fmt.Errorf("handle called on nil MsgReadWriter for new key " + keyid) 173 } 174 vrw = rw.(*PssReadWriter) 175 } 176 177 pmsg, err := ToP2pMsg(msg) 178 if err != nil { 179 return fmt.Errorf("could not decode pssmsg") 180 } 181 if asymmetric { 182 if p.pubKeyRWPool[keyid] == nil { 183 return fmt.Errorf("handle called on nil MsgReadWriter for key " + keyid) 184 } 185 vrw = p.pubKeyRWPool[keyid].(*PssReadWriter) 186 } else { 187 if p.symKeyRWPool[keyid] == nil { 188 return fmt.Errorf("handle called on nil MsgReadWriter for key " + keyid) 189 } 190 vrw = p.symKeyRWPool[keyid].(*PssReadWriter) 191 } 192 vrw.injectMsg(pmsg) 193 return nil 194 } 195 196 //检查(对等)对称密钥当前是否已注册到此主题 197 func (p *Protocol) isActiveSymKey(key string, topic Topic) bool { 198 return p.symKeyRWPool[key] != nil 199 } 200 201 //检查(对等)非对称密钥当前是否已注册到此主题 202 func (p *Protocol) isActiveAsymKey(key string, topic Topic) bool { 203 return p.pubKeyRWPool[key] != nil 204 } 205 206 //创建p2p.msg的序列化(非缓冲)版本,用于专门的内部p2p.msgreadwriter实现 207 func ToP2pMsg(msg []byte) (p2p.Msg, error) { 208 payload := &ProtocolMsg{} 209 if err := rlp.DecodeBytes(msg, payload); err != nil { 210 return p2p.Msg{}, fmt.Errorf("pss protocol handler unable to decode payload as p2p message: %v", err) 211 } 212 213 return p2p.Msg{ 214 Code: payload.Code, 215 Size: uint32(len(payload.Payload)), 216 ReceivedAt: time.Now(), 217 Payload: bytes.NewBuffer(payload.Payload), 218 }, nil 219 } 220 221 //在指定的对等机上运行模拟的PSS协议, 222 //链接到特定主题 223 //`key`和'asymmetric`指定什么加密密钥 224 //将对等机链接到。 225 //在添加对等机之前,密钥必须存在于PSS存储区中。 226 func (p *Protocol) AddPeer(peer *p2p.Peer, topic Topic, asymmetric bool, key string) (p2p.MsgReadWriter, error) { 227 rw := &PssReadWriter{ 228 Pss: p.Pss, 229 rw: make(chan p2p.Msg), 230 spec: p.spec, 231 topic: p.topic, 232 key: key, 233 } 234 if asymmetric { 235 rw.sendFunc = p.Pss.SendAsym 236 } else { 237 rw.sendFunc = p.Pss.SendSym 238 } 239 if asymmetric { 240 p.Pss.pubKeyPoolMu.Lock() 241 if _, ok := p.Pss.pubKeyPool[key]; !ok { 242 return nil, fmt.Errorf("asym key does not exist: %s", key) 243 } 244 p.Pss.pubKeyPoolMu.Unlock() 245 p.RWPoolMu.Lock() 246 p.pubKeyRWPool[key] = rw 247 p.RWPoolMu.Unlock() 248 } else { 249 p.Pss.symKeyPoolMu.Lock() 250 if _, ok := p.Pss.symKeyPool[key]; !ok { 251 return nil, fmt.Errorf("symkey does not exist: %s", key) 252 } 253 p.Pss.symKeyPoolMu.Unlock() 254 p.RWPoolMu.Lock() 255 p.symKeyRWPool[key] = rw 256 p.RWPoolMu.Unlock() 257 } 258 go func() { 259 err := p.proto.Run(peer, rw) 260 log.Warn(fmt.Sprintf("pss vprotocol quit on %v topic %v: %v", peer, topic, err)) 261 }() 262 return rw, nil 263 } 264 265 func (p *Protocol) RemovePeer(asymmetric bool, key string) { 266 log.Debug("closing pss peer", "asym", asymmetric, "key", key) 267 p.RWPoolMu.Lock() 268 defer p.RWPoolMu.Unlock() 269 if asymmetric { 270 rw := p.pubKeyRWPool[key].(*PssReadWriter) 271 rw.closed = true 272 delete(p.pubKeyRWPool, key) 273 } else { 274 rw := p.symKeyRWPool[key].(*PssReadWriter) 275 rw.closed = true 276 delete(p.symKeyRWPool, key) 277 } 278 } 279 280 //协议说明符到主题的统一翻译 281 func ProtocolTopic(spec *protocols.Spec) Topic { 282 return BytesToTopic([]byte(fmt.Sprintf("%s:%d", spec.Name, spec.Version))) 283 } 284