github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/pss/client/client.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 client 28 29 import ( 30 "context" 31 "errors" 32 "fmt" 33 "sync" 34 "time" 35 36 "github.com/ethereum/go-ethereum/common/hexutil" 37 "github.com/ethereum/go-ethereum/p2p" 38 "github.com/ethereum/go-ethereum/p2p/discover" 39 "github.com/ethereum/go-ethereum/p2p/protocols" 40 "github.com/ethereum/go-ethereum/rlp" 41 "github.com/ethereum/go-ethereum/rpc" 42 "github.com/ethereum/go-ethereum/swarm/log" 43 "github.com/ethereum/go-ethereum/swarm/pss" 44 ) 45 46 const ( 47 handshakeRetryTimeout = 1000 48 handshakeRetryCount = 3 49 ) 50 51 // 52 // 53 type Client struct { 54 BaseAddrHex string 55 56 // 57 peerPool map[pss.Topic]map[string]*pssRPCRW 58 protos map[pss.Topic]*p2p.Protocol 59 60 // 61 rpc *rpc.Client 62 subs []*rpc.ClientSubscription 63 64 // 65 topicsC chan []byte 66 quitC chan struct{} 67 68 poolMu sync.Mutex 69 } 70 71 // 72 type pssRPCRW struct { 73 *Client 74 topic string 75 msgC chan []byte 76 addr pss.PssAddress 77 pubKeyId string 78 lastSeen time.Time 79 closed bool 80 } 81 82 func (c *Client) newpssRPCRW(pubkeyid string, addr pss.PssAddress, topicobj pss.Topic) (*pssRPCRW, error) { 83 topic := topicobj.String() 84 err := c.rpc.Call(nil, "pss_setPeerPublicKey", pubkeyid, topic, hexutil.Encode(addr[:])) 85 if err != nil { 86 return nil, fmt.Errorf("setpeer %s %s: %v", topic, pubkeyid, err) 87 } 88 return &pssRPCRW{ 89 Client: c, 90 topic: topic, 91 msgC: make(chan []byte), 92 addr: addr, 93 pubKeyId: pubkeyid, 94 }, nil 95 } 96 97 func (rw *pssRPCRW) ReadMsg() (p2p.Msg, error) { 98 msg := <-rw.msgC 99 log.Trace("pssrpcrw read", "msg", msg) 100 pmsg, err := pss.ToP2pMsg(msg) 101 if err != nil { 102 return p2p.Msg{}, err 103 } 104 105 return pmsg, nil 106 } 107 108 // 109 // 110 // 111 // 112 // 113 // 114 // 115 // 116 func (rw *pssRPCRW) WriteMsg(msg p2p.Msg) error { 117 log.Trace("got writemsg pssclient", "msg", msg) 118 if rw.closed { 119 return fmt.Errorf("connection closed") 120 } 121 rlpdata := make([]byte, msg.Size) 122 msg.Payload.Read(rlpdata) 123 pmsg, err := rlp.EncodeToBytes(pss.ProtocolMsg{ 124 Code: msg.Code, 125 Size: msg.Size, 126 Payload: rlpdata, 127 }) 128 if err != nil { 129 return err 130 } 131 132 // 133 var symkeyids []string 134 err = rw.Client.rpc.Call(&symkeyids, "pss_getHandshakeKeys", rw.pubKeyId, rw.topic, false, true) 135 if err != nil { 136 return err 137 } 138 139 // 140 var symkeycap uint16 141 if len(symkeyids) > 0 { 142 err = rw.Client.rpc.Call(&symkeycap, "pss_getHandshakeKeyCapacity", symkeyids[0]) 143 if err != nil { 144 return err 145 } 146 } 147 148 err = rw.Client.rpc.Call(nil, "pss_sendSym", symkeyids[0], rw.topic, hexutil.Encode(pmsg)) 149 if err != nil { 150 return err 151 } 152 153 // 154 if symkeycap == 1 { 155 var retries int 156 var sync bool 157 // 158 if len(symkeyids) == 1 { 159 sync = true 160 } 161 // 162 _, err := rw.handshake(retries, sync, false) 163 if err != nil { 164 log.Warn("failing", "err", err) 165 return err 166 } 167 } 168 return nil 169 } 170 171 // 172 // 173 func (rw *pssRPCRW) handshake(retries int, sync bool, flush bool) (string, error) { 174 175 var symkeyids []string 176 var i int 177 // 178 // 179 for i = 0; i < 1+retries; i++ { 180 log.Debug("handshake attempt pssrpcrw", "pubkeyid", rw.pubKeyId, "topic", rw.topic, "sync", sync) 181 err := rw.Client.rpc.Call(&symkeyids, "pss_handshake", rw.pubKeyId, rw.topic, sync, flush) 182 if err == nil { 183 var keyid string 184 if sync { 185 keyid = symkeyids[0] 186 } 187 return keyid, nil 188 } 189 if i-1+retries > 1 { 190 time.Sleep(time.Millisecond * handshakeRetryTimeout) 191 } 192 } 193 194 return "", fmt.Errorf("handshake failed after %d attempts", i) 195 } 196 197 // 198 // 199 // 200 func NewClient(rpcurl string) (*Client, error) { 201 rpcclient, err := rpc.Dial(rpcurl) 202 if err != nil { 203 return nil, err 204 } 205 206 client, err := NewClientWithRPC(rpcclient) 207 if err != nil { 208 return nil, err 209 } 210 return client, nil 211 } 212 213 // 214 // 215 // 216 func NewClientWithRPC(rpcclient *rpc.Client) (*Client, error) { 217 client := newClient() 218 client.rpc = rpcclient 219 err := client.rpc.Call(&client.BaseAddrHex, "pss_baseAddr") 220 if err != nil { 221 return nil, fmt.Errorf("cannot get pss node baseaddress: %v", err) 222 } 223 return client, nil 224 } 225 226 func newClient() (client *Client) { 227 client = &Client{ 228 quitC: make(chan struct{}), 229 peerPool: make(map[pss.Topic]map[string]*pssRPCRW), 230 protos: make(map[pss.Topic]*p2p.Protocol), 231 } 232 return 233 } 234 235 // 236 // 237 // 238 // 239 // 240 // 241 // 242 func (c *Client) RunProtocol(ctx context.Context, proto *p2p.Protocol) error { 243 topicobj := pss.BytesToTopic([]byte(fmt.Sprintf("%s:%d", proto.Name, proto.Version))) 244 topichex := topicobj.String() 245 msgC := make(chan pss.APIMsg) 246 c.peerPool[topicobj] = make(map[string]*pssRPCRW) 247 sub, err := c.rpc.Subscribe(ctx, "pss", msgC, "receive", topichex) 248 if err != nil { 249 return fmt.Errorf("pss event subscription failed: %v", err) 250 } 251 c.subs = append(c.subs, sub) 252 err = c.rpc.Call(nil, "pss_addHandshake", topichex) 253 if err != nil { 254 return fmt.Errorf("pss handshake activation failed: %v", err) 255 } 256 257 // 258 go func() { 259 for { 260 select { 261 case msg := <-msgC: 262 // 263 if msg.Asymmetric { 264 continue 265 } 266 // 267 // 268 var pubkeyid string 269 err = c.rpc.Call(&pubkeyid, "pss_getHandshakePublicKey", msg.Key) 270 if err != nil || pubkeyid == "" { 271 log.Trace("proto err or no pubkey", "err", err, "symkeyid", msg.Key) 272 continue 273 } 274 // 275 // 276 if c.peerPool[topicobj][pubkeyid] == nil { 277 var addrhex string 278 err := c.rpc.Call(&addrhex, "pss_getAddress", topichex, false, msg.Key) 279 if err != nil { 280 log.Trace(err.Error()) 281 continue 282 } 283 addrbytes, err := hexutil.Decode(addrhex) 284 if err != nil { 285 log.Trace(err.Error()) 286 break 287 } 288 addr := pss.PssAddress(addrbytes) 289 rw, err := c.newpssRPCRW(pubkeyid, addr, topicobj) 290 if err != nil { 291 break 292 } 293 c.peerPool[topicobj][pubkeyid] = rw 294 nid, _ := discover.HexID("0x00") 295 p := p2p.NewPeer(nid, fmt.Sprintf("%v", addr), []p2p.Cap{}) 296 go proto.Run(p, c.peerPool[topicobj][pubkeyid]) 297 } 298 go func() { 299 c.peerPool[topicobj][pubkeyid].msgC <- msg.Msg 300 }() 301 case <-c.quitC: 302 return 303 } 304 } 305 }() 306 307 c.protos[topicobj] = proto 308 return nil 309 } 310 311 // 312 func (c *Client) Close() error { 313 for _, s := range c.subs { 314 s.Unsubscribe() 315 } 316 return nil 317 } 318 319 // 320 // 321 // 322 // 323 // 324 // 325 // 326 // 327 // 328 func (c *Client) AddPssPeer(pubkeyid string, addr []byte, spec *protocols.Spec) error { 329 topic := pss.ProtocolTopic(spec) 330 if c.peerPool[topic] == nil { 331 return errors.New("addpeer on unset topic") 332 } 333 if c.peerPool[topic][pubkeyid] == nil { 334 rw, err := c.newpssRPCRW(pubkeyid, addr, topic) 335 if err != nil { 336 return err 337 } 338 _, err = rw.handshake(handshakeRetryCount, true, true) 339 if err != nil { 340 return err 341 } 342 c.poolMu.Lock() 343 c.peerPool[topic][pubkeyid] = rw 344 c.poolMu.Unlock() 345 nid, _ := discover.HexID("0x00") 346 p := p2p.NewPeer(nid, fmt.Sprintf("%v", addr), []p2p.Cap{}) 347 go c.protos[topic].Run(p, c.peerPool[topic][pubkeyid]) 348 } 349 return nil 350 } 351 352 // 353 // 354 // 355 func (c *Client) RemovePssPeer(pubkeyid string, spec *protocols.Spec) { 356 log.Debug("closing pss client peer", "pubkey", pubkeyid, "protoname", spec.Name, "protoversion", spec.Version) 357 c.poolMu.Lock() 358 defer c.poolMu.Unlock() 359 topic := pss.ProtocolTopic(spec) 360 c.peerPool[topic][pubkeyid].closed = true 361 delete(c.peerPool[topic], pubkeyid) 362 }