github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/discv5/udp.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 //版权所有2016 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package discv5 26 27 import ( 28 "bytes" 29 "crypto/ecdsa" 30 "errors" 31 "fmt" 32 "net" 33 "time" 34 35 "github.com/ethereum/go-ethereum/common" 36 "github.com/ethereum/go-ethereum/crypto" 37 "github.com/ethereum/go-ethereum/log" 38 "github.com/ethereum/go-ethereum/p2p/nat" 39 "github.com/ethereum/go-ethereum/p2p/netutil" 40 "github.com/ethereum/go-ethereum/rlp" 41 ) 42 43 const Version = 4 44 45 //错误 46 var ( 47 errPacketTooSmall = errors.New("too small") 48 errBadPrefix = errors.New("bad prefix") 49 errTimeout = errors.New("RPC timeout") 50 ) 51 52 //超时 53 const ( 54 respTimeout = 500 * time.Millisecond 55 expiration = 20 * time.Second 56 57 driftThreshold = 10 * time.Second //警告用户前允许的时钟漂移 58 ) 59 60 //RPC请求结构 61 type ( 62 ping struct { 63 Version uint 64 From, To rpcEndpoint 65 Expiration uint64 66 67 //V5 68 Topics []Topic 69 70 //忽略其他字段(为了向前兼容)。 71 Rest []rlp.RawValue `rlp:"tail"` 72 } 73 74 //乒乓球是对乒乓球的回应。 75 pong struct { 76 //此字段应镜像UDP信封地址 77 //提供了一种发现 78 //外部地址(在NAT之后)。 79 To rpcEndpoint 80 81 ReplyTok []byte //这包含ping包的哈希。 82 Expiration uint64 //数据包失效的绝对时间戳。 83 84 //V5 85 TopicHash common.Hash 86 TicketSerial uint32 87 WaitPeriods []uint32 88 89 //忽略其他字段(为了向前兼容)。 90 Rest []rlp.RawValue `rlp:"tail"` 91 } 92 93 //findnode是对接近给定目标的节点的查询。 94 findnode struct { 95 Target NodeID //不需要是实际的公钥 96 Expiration uint64 97 //忽略其他字段(为了向前兼容)。 98 Rest []rlp.RawValue `rlp:"tail"` 99 } 100 101 //findnode是对接近给定目标的节点的查询。 102 findnodeHash struct { 103 Target common.Hash 104 Expiration uint64 105 //忽略其他字段(为了向前兼容)。 106 Rest []rlp.RawValue `rlp:"tail"` 107 } 108 109 //回复findnode 110 neighbors struct { 111 Nodes []rpcNode 112 Expiration uint64 113 //忽略其他字段(为了向前兼容)。 114 Rest []rlp.RawValue `rlp:"tail"` 115 } 116 117 topicRegister struct { 118 Topics []Topic 119 Idx uint 120 Pong []byte 121 } 122 123 topicQuery struct { 124 Topic Topic 125 Expiration uint64 126 } 127 128 //答复topicquery 129 topicNodes struct { 130 Echo common.Hash 131 Nodes []rpcNode 132 } 133 134 rpcNode struct { 135 IP net.IP //IPv4的len 4或IPv6的len 16 136 UDP uint16 //用于发现协议 137 TCP uint16 //对于RLPX协议 138 ID NodeID 139 } 140 141 rpcEndpoint struct { 142 IP net.IP //IPv4的len 4或IPv6的len 16 143 UDP uint16 //用于发现协议 144 TCP uint16 //对于RLPX协议 145 } 146 ) 147 148 var ( 149 versionPrefix = []byte("temporary discovery v5") 150 versionPrefixSize = len(versionPrefix) 151 sigSize = 520 / 8 152 headSize = versionPrefixSize + sigSize //包帧数据空间 153 ) 154 155 //邻居答复通过多个数据包发送到 156 //低于1280字节的限制。我们计算最大数 157 //通过填充一个包直到它变得太大。 158 var maxNeighbors = func() int { 159 p := neighbors{Expiration: ^uint64(0)} 160 maxSizeNode := rpcNode{IP: make(net.IP, 16), UDP: ^uint16(0), TCP: ^uint16(0)} 161 for n := 0; ; n++ { 162 p.Nodes = append(p.Nodes, maxSizeNode) 163 size, _, err := rlp.EncodeToReader(p) 164 if err != nil { 165 //如果发生这种情况,它将被单元测试捕获。 166 panic("cannot encode: " + err.Error()) 167 } 168 if headSize+size+1 >= 1280 { 169 return n 170 } 171 } 172 }() 173 174 var maxTopicNodes = func() int { 175 p := topicNodes{} 176 maxSizeNode := rpcNode{IP: make(net.IP, 16), UDP: ^uint16(0), TCP: ^uint16(0)} 177 for n := 0; ; n++ { 178 p.Nodes = append(p.Nodes, maxSizeNode) 179 size, _, err := rlp.EncodeToReader(p) 180 if err != nil { 181 //如果发生这种情况,它将被单元测试捕获。 182 panic("cannot encode: " + err.Error()) 183 } 184 if headSize+size+1 >= 1280 { 185 return n 186 } 187 } 188 }() 189 190 func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) rpcEndpoint { 191 ip := addr.IP.To4() 192 if ip == nil { 193 ip = addr.IP.To16() 194 } 195 return rpcEndpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort} 196 } 197 198 func (e1 rpcEndpoint) equal(e2 rpcEndpoint) bool { 199 return e1.UDP == e2.UDP && e1.TCP == e2.TCP && e1.IP.Equal(e2.IP) 200 } 201 202 func nodeFromRPC(sender *net.UDPAddr, rn rpcNode) (*Node, error) { 203 if err := netutil.CheckRelayIP(sender.IP, rn.IP); err != nil { 204 return nil, err 205 } 206 n := NewNode(rn.ID, rn.IP, rn.UDP, rn.TCP) 207 err := n.validateComplete() 208 return n, err 209 } 210 211 func nodeToRPC(n *Node) rpcNode { 212 return rpcNode{ID: n.ID, IP: n.IP, UDP: n.UDP, TCP: n.TCP} 213 } 214 215 type ingressPacket struct { 216 remoteID NodeID 217 remoteAddr *net.UDPAddr 218 ev nodeEvent 219 hash []byte 220 data interface{} //rpc结构之一 221 rawData []byte 222 } 223 224 type conn interface { 225 ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) 226 WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error) 227 Close() error 228 LocalAddr() net.Addr 229 } 230 231 //UDP实现RPC协议。 232 type udp struct { 233 conn conn 234 priv *ecdsa.PrivateKey 235 ourEndpoint rpcEndpoint 236 nat nat.Interface 237 net *Network 238 } 239 240 //listenudp返回一个新表,用于侦听laddr上的udp包。 241 func ListenUDP(priv *ecdsa.PrivateKey, conn conn, realaddr *net.UDPAddr, nodeDBPath string, netrestrict *netutil.Netlist) (*Network, error) { 242 transport, err := listenUDP(priv, conn, realaddr) 243 if err != nil { 244 return nil, err 245 } 246 net, err := newNetwork(transport, priv.PublicKey, nodeDBPath, netrestrict) 247 if err != nil { 248 return nil, err 249 } 250 log.Info("UDP listener up", "net", net.tab.self) 251 transport.net = net 252 go transport.readLoop() 253 return net, nil 254 } 255 256 func listenUDP(priv *ecdsa.PrivateKey, conn conn, realaddr *net.UDPAddr) (*udp, error) { 257 return &udp{conn: conn, priv: priv, ourEndpoint: makeEndpoint(realaddr, uint16(realaddr.Port))}, nil 258 } 259 260 func (t *udp) localAddr() *net.UDPAddr { 261 return t.conn.LocalAddr().(*net.UDPAddr) 262 } 263 264 func (t *udp) Close() { 265 t.conn.Close() 266 } 267 268 func (t *udp) send(remote *Node, ptype nodeEvent, data interface{}) (hash []byte) { 269 hash, _ = t.sendPacket(remote.ID, remote.addr(), byte(ptype), data) 270 return hash 271 } 272 273 func (t *udp) sendPing(remote *Node, toaddr *net.UDPAddr, topics []Topic) (hash []byte) { 274 hash, _ = t.sendPacket(remote.ID, toaddr, byte(pingPacket), ping{ 275 Version: Version, 276 From: t.ourEndpoint, 277 To: makeEndpoint(toaddr, uint16(toaddr.Port)), //TODO:可能使用数据库中已知的TCP端口 278 Expiration: uint64(time.Now().Add(expiration).Unix()), 279 Topics: topics, 280 }) 281 return hash 282 } 283 284 func (t *udp) sendFindnode(remote *Node, target NodeID) { 285 t.sendPacket(remote.ID, remote.addr(), byte(findnodePacket), findnode{ 286 Target: target, 287 Expiration: uint64(time.Now().Add(expiration).Unix()), 288 }) 289 } 290 291 func (t *udp) sendNeighbours(remote *Node, results []*Node) { 292 //以块形式发送邻居,每个数据包最多有maxneighbors 293 //低于1280字节的限制。 294 p := neighbors{Expiration: uint64(time.Now().Add(expiration).Unix())} 295 for i, result := range results { 296 p.Nodes = append(p.Nodes, nodeToRPC(result)) 297 if len(p.Nodes) == maxNeighbors || i == len(results)-1 { 298 t.sendPacket(remote.ID, remote.addr(), byte(neighborsPacket), p) 299 p.Nodes = p.Nodes[:0] 300 } 301 } 302 } 303 304 func (t *udp) sendFindnodeHash(remote *Node, target common.Hash) { 305 t.sendPacket(remote.ID, remote.addr(), byte(findnodeHashPacket), findnodeHash{ 306 Target: target, 307 Expiration: uint64(time.Now().Add(expiration).Unix()), 308 }) 309 } 310 311 func (t *udp) sendTopicRegister(remote *Node, topics []Topic, idx int, pong []byte) { 312 t.sendPacket(remote.ID, remote.addr(), byte(topicRegisterPacket), topicRegister{ 313 Topics: topics, 314 Idx: uint(idx), 315 Pong: pong, 316 }) 317 } 318 319 func (t *udp) sendTopicNodes(remote *Node, queryHash common.Hash, nodes []*Node) { 320 p := topicNodes{Echo: queryHash} 321 var sent bool 322 for _, result := range nodes { 323 if result.IP.Equal(t.net.tab.self.IP) || netutil.CheckRelayIP(remote.IP, result.IP) == nil { 324 p.Nodes = append(p.Nodes, nodeToRPC(result)) 325 } 326 if len(p.Nodes) == maxTopicNodes { 327 t.sendPacket(remote.ID, remote.addr(), byte(topicNodesPacket), p) 328 p.Nodes = p.Nodes[:0] 329 sent = true 330 } 331 } 332 if !sent || len(p.Nodes) > 0 { 333 t.sendPacket(remote.ID, remote.addr(), byte(topicNodesPacket), p) 334 } 335 } 336 337 func (t *udp) sendPacket(toid NodeID, toaddr *net.UDPAddr, ptype byte, req interface{}) (hash []byte, err error) { 338 //fmt.println(“发送包”,nodeEvent(ptype),toaddr.string(),toid.string()) 339 packet, hash, err := encodePacket(t.priv, ptype, req) 340 if err != nil { 341 //fmt.println(错误) 342 return hash, err 343 } 344 log.Trace(fmt.Sprintf(">>> %v to %x@%v", nodeEvent(ptype), toid[:8], toaddr)) 345 if nbytes, err := t.conn.WriteToUDP(packet, toaddr); err != nil { 346 log.Trace(fmt.Sprint("UDP send failed:", err)) 347 } else { 348 egressTrafficMeter.Mark(int64(nbytes)) 349 } 350 //fmt.println(错误) 351 return hash, err 352 } 353 354 //编码包的零填充空间。 355 var headSpace = make([]byte, headSize) 356 357 func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) (p, hash []byte, err error) { 358 b := new(bytes.Buffer) 359 b.Write(headSpace) 360 b.WriteByte(ptype) 361 if err := rlp.Encode(b, req); err != nil { 362 log.Error(fmt.Sprint("error encoding packet:", err)) 363 return nil, nil, err 364 } 365 packet := b.Bytes() 366 sig, err := crypto.Sign(crypto.Keccak256(packet[headSize:]), priv) 367 if err != nil { 368 log.Error(fmt.Sprint("could not sign packet:", err)) 369 return nil, nil, err 370 } 371 copy(packet, versionPrefix) 372 copy(packet[versionPrefixSize:], sig) 373 hash = crypto.Keccak256(packet[versionPrefixSize:]) 374 return packet, hash, nil 375 } 376 377 //readloop在自己的goroutine中运行。它注入入口UDP包 378 //进入网络循环。 379 func (t *udp) readLoop() { 380 defer t.conn.Close() 381 //发现数据包被定义为不大于1280字节。 382 //大于此尺寸的包装将在末端切割并处理 383 //因为它们的哈希不匹配而无效。 384 buf := make([]byte, 1280) 385 for { 386 nbytes, from, err := t.conn.ReadFromUDP(buf) 387 ingressTrafficMeter.Mark(int64(nbytes)) 388 if netutil.IsTemporaryError(err) { 389 //忽略临时读取错误。 390 log.Debug(fmt.Sprintf("Temporary read error: %v", err)) 391 continue 392 } else if err != nil { 393 //关闭永久错误循环。 394 log.Debug(fmt.Sprintf("Read error: %v", err)) 395 return 396 } 397 t.handlePacket(from, buf[:nbytes]) 398 } 399 } 400 401 func (t *udp) handlePacket(from *net.UDPAddr, buf []byte) error { 402 pkt := ingressPacket{remoteAddr: from} 403 if err := decodePacket(buf, &pkt); err != nil { 404 log.Debug(fmt.Sprintf("Bad packet from %v: %v", from, err)) 405 //fmt.println(“坏包”,err) 406 return err 407 } 408 t.net.reqReadPacket(pkt) 409 return nil 410 } 411 412 func decodePacket(buffer []byte, pkt *ingressPacket) error { 413 if len(buffer) < headSize+1 { 414 return errPacketTooSmall 415 } 416 buf := make([]byte, len(buffer)) 417 copy(buf, buffer) 418 prefix, sig, sigdata := buf[:versionPrefixSize], buf[versionPrefixSize:headSize], buf[headSize:] 419 if !bytes.Equal(prefix, versionPrefix) { 420 return errBadPrefix 421 } 422 fromID, err := recoverNodeID(crypto.Keccak256(buf[headSize:]), sig) 423 if err != nil { 424 return err 425 } 426 pkt.rawData = buf 427 pkt.hash = crypto.Keccak256(buf[versionPrefixSize:]) 428 pkt.remoteID = fromID 429 switch pkt.ev = nodeEvent(sigdata[0]); pkt.ev { 430 case pingPacket: 431 pkt.data = new(ping) 432 case pongPacket: 433 pkt.data = new(pong) 434 case findnodePacket: 435 pkt.data = new(findnode) 436 case neighborsPacket: 437 pkt.data = new(neighbors) 438 case findnodeHashPacket: 439 pkt.data = new(findnodeHash) 440 case topicRegisterPacket: 441 pkt.data = new(topicRegister) 442 case topicQueryPacket: 443 pkt.data = new(topicQuery) 444 case topicNodesPacket: 445 pkt.data = new(topicNodes) 446 default: 447 return fmt.Errorf("unknown packet type: %d", sigdata[0]) 448 } 449 s := rlp.NewStream(bytes.NewReader(sigdata[1:]), 0) 450 err = s.Decode(pkt.data) 451 return err 452 }