github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/p2p/discover/node.go (about) 1 // Copyright 2015 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 discover 18 19 import ( 20 "crypto/ecdsa" 21 "crypto/elliptic" 22 "encoding/hex" 23 "errors" 24 "fmt" 25 "math/big" 26 "math/rand" 27 "net" 28 "net/url" 29 "regexp" 30 "strconv" 31 "strings" 32 "time" 33 34 "github.com/PlatONnetwork/PlatON-Go/common" 35 "github.com/PlatONnetwork/PlatON-Go/crypto" 36 "github.com/PlatONnetwork/PlatON-Go/crypto/secp256k1" 37 ) 38 39 const NodeIDBits = 512 40 41 // Node represents a host on the network. 42 // The fields of Node may not be modified. 43 type Node struct { 44 IP net.IP // len 4 for IPv4 or 16 for IPv6 45 UDP, TCP uint16 // port numbers 46 ID NodeID // the node's public key 47 48 // This is a cached copy of sha3(ID) which is used for node 49 // distance calculations. This is part of Node in order to make it 50 // possible to write tests that need a node at a certain distance. 51 // In those tests, the content of sha will not actually correspond 52 // with ID. 53 sha common.Hash 54 55 // Time when the node was added to the table. 56 addedAt time.Time 57 } 58 59 // NewNode creates a new node. It is mostly meant to be used for 60 // testing purposes. 61 func NewNode(id NodeID, ip net.IP, udpPort, tcpPort uint16) *Node { 62 if ipv4 := ip.To4(); ipv4 != nil { 63 ip = ipv4 64 } 65 return &Node{ 66 IP: ip, 67 UDP: udpPort, 68 TCP: tcpPort, 69 ID: id, 70 sha: crypto.Keccak256Hash(id[:]), 71 } 72 } 73 74 func (n *Node) addr() *net.UDPAddr { 75 return &net.UDPAddr{IP: n.IP, Port: int(n.UDP)} 76 } 77 78 // Incomplete returns true for nodes with no IP address. 79 func (n *Node) Incomplete() bool { 80 return n.IP == nil 81 } 82 83 // checks whether n is a valid complete node. 84 func (n *Node) validateComplete() error { 85 if n.Incomplete() { 86 return errors.New("incomplete node") 87 } 88 if n.UDP == 0 { 89 return errors.New("missing UDP port") 90 } 91 if n.TCP == 0 { 92 return errors.New("missing TCP port") 93 } 94 if n.IP.IsMulticast() || n.IP.IsUnspecified() { 95 return errors.New("invalid IP (multicast/unspecified)") 96 } 97 _, err := n.ID.Pubkey() // validate the key (on curve, etc.) 98 return err 99 } 100 101 // The string representation of a Node is a URL. 102 // Please see ParseNode for a description of the format. 103 func (n *Node) String() string { 104 u := url.URL{Scheme: "enode"} 105 if n.Incomplete() { 106 u.Host = fmt.Sprintf("%x", n.ID[:]) 107 } else { 108 addr := net.TCPAddr{IP: n.IP, Port: int(n.TCP)} 109 u.User = url.User(fmt.Sprintf("%x", n.ID[:])) 110 u.Host = addr.String() 111 if n.UDP != n.TCP { 112 u.RawQuery = "discport=" + strconv.Itoa(int(n.UDP)) 113 } 114 } 115 return u.String() 116 } 117 118 var incompleteNodeURL = regexp.MustCompile("(?i)^(?:enode://)?([0-9a-f]+)$") 119 120 // ParseNode parses a node designator. 121 // 122 // There are two basic forms of node designators 123 // - incomplete nodes, which only have the public key (node ID) 124 // - complete nodes, which contain the public key and IP/Port information 125 // 126 // For incomplete nodes, the designator must look like one of these 127 // 128 // enode://<hex node id> 129 // <hex node id> 130 // 131 // For complete nodes, the node ID is encoded in the username portion 132 // of the URL, separated from the host by an @ sign. The hostname can 133 // only be given as an IP address, DNS domain names are not allowed. 134 // The port in the host name section is the TCP listening port. If the 135 // TCP and UDP (discovery) ports differ, the UDP port is specified as 136 // query parameter "discport". 137 // 138 // In the following example, the node URL describes 139 // a node with IP address 10.3.58.6, TCP listening port 16789 140 // and UDP discovery port 30301. 141 // 142 // enode://<hex node id>@10.3.58.6:30303?discport=30301 143 func ParseNode(rawurl string) (*Node, error) { 144 if m := incompleteNodeURL.FindStringSubmatch(rawurl); m != nil { 145 id, err := HexID(m[1]) 146 if err != nil { 147 return nil, fmt.Errorf("invalid node ID (%v)", err) 148 } 149 return NewNode(id, nil, 0, 0), nil 150 } 151 return parseComplete(rawurl) 152 } 153 154 func parseComplete(rawurl string) (*Node, error) { 155 var ( 156 id NodeID 157 ip net.IP 158 tcpPort, udpPort uint64 159 ) 160 u, err := url.Parse(rawurl) 161 if err != nil { 162 return nil, err 163 } 164 if u.Scheme != "enode" { 165 return nil, errors.New("invalid URL scheme, want \"enode\"") 166 } 167 // Parse the Node ID from the user portion. 168 if u.User == nil { 169 return nil, errors.New("does not contain node ID") 170 } 171 if id, err = HexID(u.User.String()); err != nil { 172 return nil, fmt.Errorf("invalid node ID (%v)", err) 173 } 174 // Parse the IP address. 175 host, port, err := net.SplitHostPort(u.Host) 176 if err != nil { 177 return nil, fmt.Errorf("invalid host: %v", err) 178 } 179 if ip = net.ParseIP(host); ip == nil { 180 if ips, err := net.LookupIP(host); (err == nil && len(ips) != 0) { 181 ip = ips[0] 182 } else { 183 return nil, errors.New("invalid IP address") 184 } 185 } 186 // Ensure the IP is 4 bytes long for IPv4 addresses. 187 if ipv4 := ip.To4(); ipv4 != nil { 188 ip = ipv4 189 } 190 // Parse the port numbers. 191 if tcpPort, err = strconv.ParseUint(port, 10, 16); err != nil { 192 return nil, errors.New("invalid port") 193 } 194 udpPort = tcpPort 195 qv := u.Query() 196 if qv.Get("discport") != "" { 197 udpPort, err = strconv.ParseUint(qv.Get("discport"), 10, 16) 198 if err != nil { 199 return nil, errors.New("invalid discport in query") 200 } 201 } 202 return NewNode(id, ip, uint16(udpPort), uint16(tcpPort)), nil 203 } 204 205 // MustParseNode parses a node URL. It panics if the URL is not valid. 206 func MustParseNode(rawurl string) *Node { 207 n, err := ParseNode(rawurl) 208 if err != nil { 209 panic("invalid node URL: " + err.Error()) 210 } 211 return n 212 } 213 214 // MarshalText implements encoding.TextMarshaler. 215 func (n *Node) MarshalText() ([]byte, error) { 216 return []byte(n.String()), nil 217 } 218 219 // UnmarshalText implements encoding.TextUnmarshaler. 220 func (n *Node) UnmarshalText(text []byte) error { 221 dec, err := ParseNode(string(text)) 222 if err == nil { 223 *n = *dec 224 } 225 return err 226 } 227 228 // NodeID is a unique identifier for each node. 229 // The node identifier is a marshaled elliptic curve public key. 230 type NodeID [NodeIDBits / 8]byte 231 232 // Bytes returns a byte slice representation of the NodeID 233 func (n NodeID) Bytes() []byte { 234 return n[:] 235 } 236 237 // NodeID prints as a long hexadecimal number. 238 func (n NodeID) String() string { 239 return fmt.Sprintf("%x", n[:]) 240 } 241 242 // The Go syntax representation of a NodeID is a call to HexID. 243 func (n NodeID) GoString() string { 244 return fmt.Sprintf("discover.HexID(\"%x\")", n[:]) 245 } 246 247 // TerminalString returns a shortened hex string for terminal logging. 248 func (n NodeID) TerminalString() string { 249 return hex.EncodeToString(n[:8]) 250 } 251 252 // MarshalText implements the encoding.TextMarshaler interface. 253 func (n NodeID) MarshalText() ([]byte, error) { 254 return []byte(hex.EncodeToString(n[:])), nil 255 } 256 257 // UnmarshalText implements the encoding.TextUnmarshaler interface. 258 func (n *NodeID) UnmarshalText(text []byte) error { 259 id, err := HexID(string(text)) 260 if err != nil { 261 return err 262 } 263 *n = id 264 return nil 265 } 266 267 // BytesID converts a byte slice to a NodeID 268 func BytesID(b []byte) (NodeID, error) { 269 var id NodeID 270 if len(b) != len(id) { 271 return id, fmt.Errorf("wrong length, want %d bytes", len(id)) 272 } 273 copy(id[:], b) 274 return id, nil 275 } 276 277 // MustBytesID converts a byte slice to a NodeID. 278 // It panics if the byte slice is not a valid NodeID. 279 func MustBytesID(b []byte) NodeID { 280 id, err := BytesID(b) 281 if err != nil { 282 panic(err) 283 } 284 return id 285 } 286 287 // HexID converts a hex string to a NodeID. 288 // The string may be prefixed with 0x. 289 func HexID(in string) (NodeID, error) { 290 var id NodeID 291 b, err := hex.DecodeString(strings.TrimPrefix(in, "0x")) 292 if err != nil { 293 return id, err 294 } else if len(b) != len(id) { 295 return id, fmt.Errorf("wrong length, want %d hex chars", len(id)*2) 296 } 297 copy(id[:], b) 298 return id, nil 299 } 300 301 // MustHexID converts a hex string to a NodeID. 302 // It panics if the string is not a valid NodeID. 303 func MustHexID(in string) NodeID { 304 id, err := HexID(in) 305 if err != nil { 306 panic(err) 307 } 308 return id 309 } 310 311 // PubkeyID returns a marshaled representation of the given public key. 312 func PubkeyID(pub *ecdsa.PublicKey) NodeID { 313 var id NodeID 314 pbytes := elliptic.Marshal(pub.Curve, pub.X, pub.Y) 315 if len(pbytes)-1 != len(id) { 316 panic(fmt.Errorf("need %d bit pubkey, got %d bits", (len(id)+1)*8, len(pbytes))) 317 } 318 copy(id[:], pbytes[1:]) 319 return id 320 } 321 322 // Pubkey returns the public key represented by the node ID. 323 // It returns an error if the ID is not a point on the curve. 324 func (id NodeID) Pubkey() (*ecdsa.PublicKey, error) { 325 p := &ecdsa.PublicKey{Curve: crypto.S256(), X: new(big.Int), Y: new(big.Int)} 326 half := len(id) / 2 327 p.X.SetBytes(id[:half]) 328 p.Y.SetBytes(id[half:]) 329 if !p.Curve.IsOnCurve(p.X, p.Y) { 330 return nil, errors.New("id is invalid secp256k1 curve point") 331 } 332 return p, nil 333 } 334 335 // recoverNodeID computes the public key used to sign the 336 // given hash from the signature. 337 func recoverNodeID(hash, sig []byte) (id NodeID, err error) { 338 pubkey, err := secp256k1.RecoverPubkey(hash, sig) 339 if err != nil { 340 return id, err 341 } 342 if len(pubkey)-1 != len(id) { 343 return id, fmt.Errorf("recovered pubkey has %d bits, want %d bits", len(pubkey)*8, (len(id)+1)*8) 344 } 345 for i := range id { 346 id[i] = pubkey[i+1] 347 } 348 return id, nil 349 } 350 351 // distcmp compares the distances a->target and b->target. 352 // Returns -1 if a is closer to target, 1 if b is closer to target 353 // and 0 if they are equal. 354 func distcmp(target, a, b common.Hash) int { 355 for i := range target { 356 da := a[i] ^ target[i] 357 db := b[i] ^ target[i] 358 if da > db { 359 return 1 360 } else if da < db { 361 return -1 362 } 363 } 364 return 0 365 } 366 367 // table of leading zero counts for bytes [0..255] 368 var lzcount = [256]int{ 369 8, 7, 6, 6, 5, 5, 5, 5, 370 4, 4, 4, 4, 4, 4, 4, 4, 371 3, 3, 3, 3, 3, 3, 3, 3, 372 3, 3, 3, 3, 3, 3, 3, 3, 373 2, 2, 2, 2, 2, 2, 2, 2, 374 2, 2, 2, 2, 2, 2, 2, 2, 375 2, 2, 2, 2, 2, 2, 2, 2, 376 2, 2, 2, 2, 2, 2, 2, 2, 377 1, 1, 1, 1, 1, 1, 1, 1, 378 1, 1, 1, 1, 1, 1, 1, 1, 379 1, 1, 1, 1, 1, 1, 1, 1, 380 1, 1, 1, 1, 1, 1, 1, 1, 381 1, 1, 1, 1, 1, 1, 1, 1, 382 1, 1, 1, 1, 1, 1, 1, 1, 383 1, 1, 1, 1, 1, 1, 1, 1, 384 1, 1, 1, 1, 1, 1, 1, 1, 385 0, 0, 0, 0, 0, 0, 0, 0, 386 0, 0, 0, 0, 0, 0, 0, 0, 387 0, 0, 0, 0, 0, 0, 0, 0, 388 0, 0, 0, 0, 0, 0, 0, 0, 389 0, 0, 0, 0, 0, 0, 0, 0, 390 0, 0, 0, 0, 0, 0, 0, 0, 391 0, 0, 0, 0, 0, 0, 0, 0, 392 0, 0, 0, 0, 0, 0, 0, 0, 393 0, 0, 0, 0, 0, 0, 0, 0, 394 0, 0, 0, 0, 0, 0, 0, 0, 395 0, 0, 0, 0, 0, 0, 0, 0, 396 0, 0, 0, 0, 0, 0, 0, 0, 397 0, 0, 0, 0, 0, 0, 0, 0, 398 0, 0, 0, 0, 0, 0, 0, 0, 399 0, 0, 0, 0, 0, 0, 0, 0, 400 0, 0, 0, 0, 0, 0, 0, 0, 401 } 402 403 // logdist returns the logarithmic distance between a and b, log2(a ^ b). 404 func logdist(a, b common.Hash) int { 405 lz := 0 406 for i := range a { 407 x := a[i] ^ b[i] 408 if x == 0 { 409 lz += 8 410 } else { 411 lz += lzcount[x] 412 break 413 } 414 } 415 return len(a)*8 - lz 416 } 417 418 // hashAtDistance returns a random hash such that logdist(a, b) == n 419 func hashAtDistance(a common.Hash, n int) (b common.Hash) { 420 if n == 0 { 421 return a 422 } 423 // flip bit at position n, fill the rest with random bits 424 b = a 425 pos := len(a) - n/8 - 1 426 bit := byte(0x01) << (byte(n%8) - 1) 427 if bit == 0 { 428 pos++ 429 bit = 0x80 430 } 431 b[pos] = a[pos]&^bit | ^a[pos]&bit // TODO: randomize end bits 432 for i := pos + 1; i < len(a); i++ { 433 b[i] = byte(rand.Intn(255)) 434 } 435 return b 436 }