github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/p2p/discv5/udp.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package discv5 18 19 import ( 20 "bytes" 21 "crypto/ecdsa" 22 "errors" 23 "fmt" 24 "net" 25 "time" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/crypto" 29 "github.com/ethereum/go-ethereum/log" 30 "github.com/ethereum/go-ethereum/p2p/nat" 31 "github.com/ethereum/go-ethereum/p2p/netutil" 32 "github.com/ethereum/go-ethereum/rlp" 33 ) 34 35 const Version = 4 36 37 var celoClientSalt = []byte{0x63, 0x65, 0x6C, 0x6F} 38 39 // Errors 40 var ( 41 errPacketTooSmall = errors.New("too small") 42 errBadPrefix = errors.New("bad prefix") 43 errTimeout = errors.New("RPC timeout") 44 ) 45 46 // Timeouts 47 const ( 48 respTimeout = 500 * time.Millisecond 49 expiration = 20 * time.Second 50 51 driftThreshold = 10 * time.Second // Allowed clock drift before warning user 52 ) 53 54 // RPC request structures 55 type ( 56 ping struct { 57 Version uint 58 From, To rpcEndpoint 59 Expiration uint64 60 61 // v5 62 Topics []Topic 63 64 // Ignore additional fields (for forward compatibility). 65 Rest []rlp.RawValue `rlp:"tail"` 66 } 67 68 // pong is the reply to ping. 69 pong struct { 70 // This field should mirror the UDP envelope address 71 // of the ping packet, which provides a way to discover the 72 // the external address (after NAT). 73 To rpcEndpoint 74 75 ReplyTok []byte // This contains the hash of the ping packet. 76 Expiration uint64 // Absolute timestamp at which the packet becomes invalid. 77 78 // v5 79 TopicHash common.Hash 80 TicketSerial uint32 81 WaitPeriods []uint32 82 83 // Ignore additional fields (for forward compatibility). 84 Rest []rlp.RawValue `rlp:"tail"` 85 } 86 87 // findnode is a query for nodes close to the given target. 88 findnode struct { 89 Target NodeID // doesn't need to be an actual public key 90 Expiration uint64 91 // Ignore additional fields (for forward compatibility). 92 Rest []rlp.RawValue `rlp:"tail"` 93 } 94 95 // findnode is a query for nodes close to the given target. 96 findnodeHash struct { 97 Target common.Hash 98 Expiration uint64 99 // Ignore additional fields (for forward compatibility). 100 Rest []rlp.RawValue `rlp:"tail"` 101 } 102 103 // reply to findnode 104 neighbors struct { 105 Nodes []rpcNode 106 Expiration uint64 107 // Ignore additional fields (for forward compatibility). 108 Rest []rlp.RawValue `rlp:"tail"` 109 } 110 111 topicRegister struct { 112 Topics []Topic 113 Idx uint 114 Pong []byte 115 } 116 117 topicQuery struct { 118 Topic Topic 119 Expiration uint64 120 } 121 122 // reply to topicQuery 123 topicNodes struct { 124 Echo common.Hash 125 Nodes []rpcNode 126 } 127 128 rpcNode struct { 129 IP net.IP // len 4 for IPv4 or 16 for IPv6 130 UDP uint16 // for discovery protocol 131 TCP uint16 // for RLPx protocol 132 ID NodeID 133 } 134 135 rpcEndpoint struct { 136 IP net.IP // len 4 for IPv4 or 16 for IPv6 137 UDP uint16 // for discovery protocol 138 TCP uint16 // for RLPx protocol 139 } 140 ) 141 142 var ( 143 versionPrefix = []byte("temporary discovery v5") 144 versionPrefixSize = len(versionPrefix) 145 sigSize = 520 / 8 146 headSize = versionPrefixSize + sigSize // space of packet frame data 147 ) 148 149 // Neighbors replies are sent across multiple packets to 150 // stay below the 1280 byte limit. We compute the maximum number 151 // of entries by stuffing a packet until it grows too large. 152 var maxNeighbors = func() int { 153 p := neighbors{Expiration: ^uint64(0)} 154 maxSizeNode := rpcNode{IP: make(net.IP, 16), UDP: ^uint16(0), TCP: ^uint16(0)} 155 for n := 0; ; n++ { 156 p.Nodes = append(p.Nodes, maxSizeNode) 157 size, _, err := rlp.EncodeToReader(p) 158 if err != nil { 159 // If this ever happens, it will be caught by the unit tests. 160 panic("cannot encode: " + err.Error()) 161 } 162 if headSize+size+1 >= 1280 { 163 return n 164 } 165 } 166 }() 167 168 var maxTopicNodes = func() int { 169 p := topicNodes{} 170 maxSizeNode := rpcNode{IP: make(net.IP, 16), UDP: ^uint16(0), TCP: ^uint16(0)} 171 for n := 0; ; n++ { 172 p.Nodes = append(p.Nodes, maxSizeNode) 173 size, _, err := rlp.EncodeToReader(p) 174 if err != nil { 175 // If this ever happens, it will be caught by the unit tests. 176 panic("cannot encode: " + err.Error()) 177 } 178 if headSize+size+1 >= 1280 { 179 return n 180 } 181 } 182 }() 183 184 func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) rpcEndpoint { 185 ip := addr.IP.To4() 186 if ip == nil { 187 ip = addr.IP.To16() 188 } 189 return rpcEndpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort} 190 } 191 192 func (e1 rpcEndpoint) equal(e2 rpcEndpoint) bool { 193 return e1.UDP == e2.UDP && e1.TCP == e2.TCP && e1.IP.Equal(e2.IP) 194 } 195 196 func nodeFromRPC(sender *net.UDPAddr, rn rpcNode) (*Node, error) { 197 if err := netutil.CheckRelayIP(sender.IP, rn.IP); err != nil { 198 return nil, err 199 } 200 n := NewNode(rn.ID, rn.IP, rn.UDP, rn.TCP) 201 err := n.validateComplete() 202 return n, err 203 } 204 205 func nodeToRPC(n *Node) rpcNode { 206 return rpcNode{ID: n.ID, IP: n.IP, UDP: n.UDP, TCP: n.TCP} 207 } 208 209 type ingressPacket struct { 210 remoteID NodeID 211 remoteAddr *net.UDPAddr 212 ev nodeEvent 213 hash []byte 214 data interface{} // one of the RPC structs 215 rawData []byte 216 } 217 218 type conn interface { 219 ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) 220 WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error) 221 Close() error 222 LocalAddr() net.Addr 223 } 224 225 // udp implements the RPC protocol. 226 type udp struct { 227 conn conn 228 priv *ecdsa.PrivateKey 229 ourEndpoint rpcEndpoint 230 nat nat.Interface 231 net *Network 232 } 233 234 // ListenUDP returns a new table that listens for UDP packets on laddr. 235 func ListenUDP(priv *ecdsa.PrivateKey, conn conn, nodeDBPath string, netrestrict *netutil.Netlist) (*Network, error) { 236 realaddr := conn.LocalAddr().(*net.UDPAddr) 237 transport, err := listenUDP(priv, conn, realaddr) 238 if err != nil { 239 return nil, err 240 } 241 net, err := newNetwork(transport, priv.PublicKey, nodeDBPath, netrestrict) 242 if err != nil { 243 return nil, err 244 } 245 log.Info("UDP listener up", "net", net.tab.self) 246 transport.net = net 247 go transport.readLoop() 248 return net, nil 249 } 250 251 func listenUDP(priv *ecdsa.PrivateKey, conn conn, realaddr *net.UDPAddr) (*udp, error) { 252 return &udp{conn: conn, priv: priv, ourEndpoint: makeEndpoint(realaddr, uint16(realaddr.Port))}, nil 253 } 254 255 func (t *udp) localAddr() *net.UDPAddr { 256 return t.conn.LocalAddr().(*net.UDPAddr) 257 } 258 259 func (t *udp) Close() { 260 t.conn.Close() 261 } 262 263 func (t *udp) send(remote *Node, ptype nodeEvent, data interface{}) (hash []byte) { 264 hash, _ = t.sendPacket(remote.ID, remote.addr(), byte(ptype), data) 265 return hash 266 } 267 268 func (t *udp) sendPing(remote *Node, toaddr *net.UDPAddr, topics []Topic) (hash []byte) { 269 hash, _ = t.sendPacket(remote.ID, toaddr, byte(pingPacket), ping{ 270 Version: Version, 271 From: t.ourEndpoint, 272 To: makeEndpoint(toaddr, uint16(toaddr.Port)), // TODO: maybe use known TCP port from DB 273 Expiration: uint64(time.Now().Add(expiration).Unix()), 274 Topics: topics, 275 }) 276 return hash 277 } 278 279 func (t *udp) sendFindnode(remote *Node, target NodeID) { 280 t.sendPacket(remote.ID, remote.addr(), byte(findnodePacket), findnode{ 281 Target: target, 282 Expiration: uint64(time.Now().Add(expiration).Unix()), 283 }) 284 } 285 286 func (t *udp) sendNeighbours(remote *Node, results []*Node) { 287 // Send neighbors in chunks with at most maxNeighbors per packet 288 // to stay below the 1280 byte limit. 289 p := neighbors{Expiration: uint64(time.Now().Add(expiration).Unix())} 290 for i, result := range results { 291 p.Nodes = append(p.Nodes, nodeToRPC(result)) 292 if len(p.Nodes) == maxNeighbors || i == len(results)-1 { 293 t.sendPacket(remote.ID, remote.addr(), byte(neighborsPacket), p) 294 p.Nodes = p.Nodes[:0] 295 } 296 } 297 } 298 299 func (t *udp) sendFindnodeHash(remote *Node, target common.Hash) { 300 t.sendPacket(remote.ID, remote.addr(), byte(findnodeHashPacket), findnodeHash{ 301 Target: target, 302 Expiration: uint64(time.Now().Add(expiration).Unix()), 303 }) 304 } 305 306 func (t *udp) sendTopicRegister(remote *Node, topics []Topic, idx int, pong []byte) { 307 t.sendPacket(remote.ID, remote.addr(), byte(topicRegisterPacket), topicRegister{ 308 Topics: topics, 309 Idx: uint(idx), 310 Pong: pong, 311 }) 312 } 313 314 func (t *udp) sendTopicNodes(remote *Node, queryHash common.Hash, nodes []*Node) { 315 p := topicNodes{Echo: queryHash} 316 var sent bool 317 for _, result := range nodes { 318 if result.IP.Equal(t.net.tab.self.IP) || netutil.CheckRelayIP(remote.IP, result.IP) == nil { 319 p.Nodes = append(p.Nodes, nodeToRPC(result)) 320 } 321 if len(p.Nodes) == maxTopicNodes { 322 t.sendPacket(remote.ID, remote.addr(), byte(topicNodesPacket), p) 323 p.Nodes = p.Nodes[:0] 324 sent = true 325 } 326 } 327 if !sent || len(p.Nodes) > 0 { 328 t.sendPacket(remote.ID, remote.addr(), byte(topicNodesPacket), p) 329 } 330 } 331 332 func (t *udp) sendPacket(toid NodeID, toaddr *net.UDPAddr, ptype byte, req interface{}) (hash []byte, err error) { 333 //fmt.Println("sendPacket", nodeEvent(ptype), toaddr.String(), toid.String()) 334 packet, hash, err := encodePacket(t.priv, ptype, req) 335 if err != nil { 336 //fmt.Println(err) 337 return hash, err 338 } 339 log.Trace(fmt.Sprintf(">>> %v to %x@%v", nodeEvent(ptype), toid[:8], toaddr)) 340 if nbytes, err := t.conn.WriteToUDP(packet, toaddr); err != nil { 341 log.Trace(fmt.Sprint("UDP send failed:", err)) 342 } else { 343 egressTrafficMeter.Mark(int64(nbytes)) 344 } 345 //fmt.Println(err) 346 return hash, err 347 } 348 349 // zeroed padding space for encodePacket. 350 var headSpace = make([]byte, headSize) 351 352 func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) (p, hash []byte, err error) { 353 b := new(bytes.Buffer) 354 b.Write(headSpace) 355 b.WriteByte(ptype) 356 if err := rlp.Encode(b, req); err != nil { 357 log.Error(fmt.Sprint("error encoding packet:", err)) 358 return nil, nil, err 359 } 360 packet := b.Bytes() 361 sig, err := crypto.Sign(crypto.Keccak256(packet[headSize:], celoClientSalt), priv) 362 if err != nil { 363 log.Error(fmt.Sprint("could not sign packet:", err)) 364 return nil, nil, err 365 } 366 copy(packet, versionPrefix) 367 copy(packet[versionPrefixSize:], sig) 368 hash = crypto.Keccak256(packet[versionPrefixSize:]) 369 return packet, hash, nil 370 } 371 372 // readLoop runs in its own goroutine. it injects ingress UDP packets 373 // into the network loop. 374 func (t *udp) readLoop() { 375 defer t.conn.Close() 376 // Discovery packets are defined to be no larger than 1280 bytes. 377 // Packets larger than this size will be cut at the end and treated 378 // as invalid because their hash won't match. 379 buf := make([]byte, 1280) 380 for { 381 nbytes, from, err := t.conn.ReadFromUDP(buf) 382 ingressTrafficMeter.Mark(int64(nbytes)) 383 if netutil.IsTemporaryError(err) { 384 // Ignore temporary read errors. 385 log.Debug(fmt.Sprintf("Temporary read error: %v", err)) 386 continue 387 } else if err != nil { 388 // Shut down the loop for permament errors. 389 log.Debug(fmt.Sprintf("Read error: %v", err)) 390 return 391 } 392 t.handlePacket(from, buf[:nbytes]) 393 } 394 } 395 396 func (t *udp) handlePacket(from *net.UDPAddr, buf []byte) error { 397 pkt := ingressPacket{remoteAddr: from} 398 if err := decodePacket(buf, &pkt); err != nil { 399 log.Debug(fmt.Sprintf("Bad packet from %v: %v", from, err)) 400 //fmt.Println("bad packet", err) 401 return err 402 } 403 t.net.reqReadPacket(pkt) 404 return nil 405 } 406 407 func decodePacket(buffer []byte, pkt *ingressPacket) error { 408 if len(buffer) < headSize+1 { 409 return errPacketTooSmall 410 } 411 buf := make([]byte, len(buffer)) 412 copy(buf, buffer) 413 prefix, sig, sigdata := buf[:versionPrefixSize], buf[versionPrefixSize:headSize], buf[headSize:] 414 if !bytes.Equal(prefix, versionPrefix) { 415 return errBadPrefix 416 } 417 fromID, err := recoverNodeID(crypto.Keccak256(buf[headSize:], celoClientSalt), sig) 418 if err != nil { 419 return err 420 } 421 pkt.rawData = buf 422 pkt.hash = crypto.Keccak256(buf[versionPrefixSize:]) 423 pkt.remoteID = fromID 424 switch pkt.ev = nodeEvent(sigdata[0]); pkt.ev { 425 case pingPacket: 426 pkt.data = new(ping) 427 case pongPacket: 428 pkt.data = new(pong) 429 case findnodePacket: 430 pkt.data = new(findnode) 431 case neighborsPacket: 432 pkt.data = new(neighbors) 433 case findnodeHashPacket: 434 pkt.data = new(findnodeHash) 435 case topicRegisterPacket: 436 pkt.data = new(topicRegister) 437 case topicQueryPacket: 438 pkt.data = new(topicQuery) 439 case topicNodesPacket: 440 pkt.data = new(topicNodes) 441 default: 442 return fmt.Errorf("unknown packet type: %d", sigdata[0]) 443 } 444 s := rlp.NewStream(bytes.NewReader(sigdata[1:]), 0) 445 err = s.Decode(pkt.data) 446 return err 447 }