github.com/annchain/OG@v0.0.9/p2p/discv5/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 discv5 18 19 import ( 20 "crypto/ecdsa" 21 "crypto/elliptic" 22 "encoding/hex" 23 "errors" 24 "fmt" 25 "github.com/annchain/OG/arefactor/og/types" 26 "github.com/annchain/OG/deprecated/ogcrypto" 27 "math/big" 28 "math/rand" 29 "net" 30 "net/url" 31 "regexp" 32 "strconv" 33 "strings" 34 ) 35 36 // Node represents a host on the network. 37 // The public fields of Node may not be modified. 38 //go:generate msgp 39 //msgp:tuple Node 40 type Node struct { 41 //IP net.IP // len 4 for IPv4 or 16 for IPv6 42 IP []byte 43 UDP, TCP uint16 // port numbers 44 //ID NodeID // the node's public key 45 ID [64]byte 46 47 // Network-related fields are contained in nodeNetGuts. 48 // These fields are not supposed to be used off the 49 // Network.loop goroutine. 50 nodeNetGuts 51 } 52 53 // NewNode creates a new node. It is mostly meant to be used for 54 // testing purposes. 55 func NewNode(id NodeID, ip net.IP, udpPort, tcpPort uint16) *Node { 56 if ipv4 := ip.To4(); ipv4 != nil { 57 ip = ipv4 58 } 59 return &Node{ 60 IP: ip, 61 UDP: udpPort, 62 TCP: tcpPort, 63 ID: id, 64 nodeNetGuts: nodeNetGuts{sha: ogcrypto.Keccak256Hash(id[:])}, 65 } 66 } 67 68 func (n *Node) addr() *net.UDPAddr { 69 return &net.UDPAddr{IP: n.IP, Port: int(n.UDP)} 70 } 71 72 func (n *Node) setAddr(a *net.UDPAddr) { 73 n.IP = a.IP 74 if ipv4 := a.IP.To4(); ipv4 != nil { 75 n.IP = ipv4 76 } 77 n.UDP = uint16(a.Port) 78 } 79 80 // compares the given address against the stored values. 81 func (n *Node) addrEqual(a *net.UDPAddr) bool { 82 ip := a.IP 83 if ipv4 := a.IP.To4(); ipv4 != nil { 84 ip = ipv4 85 } 86 IP := net.IP(n.IP) 87 return n.UDP == uint16(a.Port) && IP.Equal(ip) 88 } 89 90 // Incomplete returns true for nodes with no IP address. 91 func (n *Node) Incomplete() bool { 92 return n.IP == nil 93 } 94 95 // checks whether n is a valid complete node. 96 func (n *Node) validateComplete() error { 97 if n.Incomplete() { 98 return errors.New("incomplete node") 99 } 100 if n.UDP == 0 { 101 return errors.New("missing UDP port") 102 } 103 if n.TCP == 0 { 104 return errors.New("missing TCP port") 105 } 106 IP := net.IP(n.IP) 107 if IP.IsMulticast() || IP.IsUnspecified() { 108 return errors.New("invalid IP (multicast/unspecified)") 109 } 110 ID := NodeID(n.ID) 111 _, err := ID.Pubkey() // validate the key (on curve, etc.) 112 return err 113 } 114 115 // The string representation of a Node is a URL. 116 // Please see ParseNode for a description of the format. 117 func (n *Node) String() string { 118 u := url.URL{Scheme: "onode"} 119 if n.Incomplete() { 120 u.Host = fmt.Sprintf("%x", n.ID[:]) 121 } else { 122 addr := net.TCPAddr{IP: n.IP, Port: int(n.TCP)} 123 u.User = url.User(fmt.Sprintf("%x", n.ID[:])) 124 u.Host = addr.String() 125 if n.UDP != n.TCP { 126 u.RawQuery = "discport=" + strconv.Itoa(int(n.UDP)) 127 } 128 } 129 return u.String() 130 } 131 132 var incompleteNodeURL = regexp.MustCompile("(?i)^(?:onode://)?([0-9a-f]+)$") 133 134 // ParseNode parses a node designator. 135 // 136 // There are two basic forms of node designators 137 // - incomplete nodes, which only have the public key (node ID) 138 // - complete nodes, which contain the public key and IP/Port information 139 // 140 // For incomplete nodes, the designator must look like one of these 141 // 142 // onode://<hex node id> 143 // <hex node id> 144 // 145 // For complete nodes, the node ID is encoded in the username portion 146 // of the URL, separated from the host by an @ sign. The hostname can 147 // only be given as an IP address, DNS domain names are not allowed. 148 // The port in the host name section is the TCP listening port. If the 149 // TCP and UDP (discovery) ports differ, the UDP port is specified as 150 // query parameter "discport". 151 // 152 // In the following example, the node URL describes 153 // a node with IP address 10.3.58.6, TCP listening port 30303 154 // and UDP discovery port 30301. 155 // 156 // onode://<hex node id>@10.3.58.6:30303?discport=30301 157 func ParseNode(rawurl string) (*Node, error) { 158 if m := incompleteNodeURL.FindStringSubmatch(rawurl); m != nil { 159 id, err := HexID(m[1]) 160 if err != nil { 161 return nil, fmt.Errorf("invalid node ID (%v)", err) 162 } 163 return NewNode(id, nil, 0, 0), nil 164 } 165 return parseComplete(rawurl) 166 } 167 168 func parseComplete(rawurl string) (*Node, error) { 169 var ( 170 id NodeID 171 ip net.IP 172 tcpPort, udpPort uint64 173 ) 174 u, err := url.Parse(rawurl) 175 if err != nil { 176 return nil, err 177 } 178 if u.Scheme != "onode" { 179 return nil, errors.New("invalid URL scheme, want \"onode\"") 180 } 181 // Parse the Node ID from the user portion. 182 if u.User == nil { 183 return nil, errors.New("does not contain node ID") 184 } 185 if id, err = HexID(u.User.String()); err != nil { 186 return nil, fmt.Errorf("invalid node ID (%v)", err) 187 } 188 // Parse the IP address. 189 host, port, err := net.SplitHostPort(u.Host) 190 if err != nil { 191 return nil, fmt.Errorf("invalid host: %v", err) 192 } 193 if ip = net.ParseIP(host); ip == nil { 194 return nil, errors.New("invalid IP address") 195 } 196 // Ensure the IP is 4 bytes long for IPv4 addresses. 197 if ipv4 := ip.To4(); ipv4 != nil { 198 ip = ipv4 199 } 200 // Parse the port numbers. 201 if tcpPort, err = strconv.ParseUint(port, 10, 16); err != nil { 202 return nil, errors.New("invalid port") 203 } 204 udpPort = tcpPort 205 qv := u.Query() 206 if qv.Get("discport") != "" { 207 udpPort, err = strconv.ParseUint(qv.Get("discport"), 10, 16) 208 if err != nil { 209 return nil, errors.New("invalid discport in query") 210 } 211 } 212 return NewNode(id, ip, uint16(udpPort), uint16(tcpPort)), nil 213 } 214 215 // MustParseNode parses a node URL. It panics if the URL is not valid. 216 func MustParseNode(rawurl string) *Node { 217 n, err := ParseNode(rawurl) 218 if err != nil { 219 panic("invalid node URL: " + err.Error()) 220 } 221 return n 222 } 223 224 // MarshalText implements encoding.TextMarshaler. 225 func (n *Node) MarshalText() ([]byte, error) { 226 return []byte(n.String()), nil 227 } 228 229 // UnmarshalText implements encoding.TextUnmarshaler. 230 func (n *Node) UnmarshalText(text []byte) error { 231 dec, err := ParseNode(string(text)) 232 if err == nil { 233 *n = *dec 234 } 235 return err 236 } 237 238 // type nodeQueue []*Node 239 // 240 // // pushNew adds n to the end if it is not present. 241 // func (nl *nodeList) appendNew(n *Node) { 242 // for _, entry := range n { 243 // if entry == n { 244 // return 245 // } 246 // } 247 // *nq = append(*nq, n) 248 // } 249 // 250 // // popRandom removes a random node. Nodes closer to 251 // // to the head of the beginning of the have a slightly higher probability. 252 // func (nl *nodeList) popRandom() *Node { 253 // ix := rand.Intn(len(*nq)) 254 // //TODO: probability as mentioned above. 255 // nl.removeIndex(ix) 256 // } 257 // 258 // func (nl *nodeList) removeIndex(i int) *Node { 259 // slice = *nl 260 // if len(*slice) <= i { 261 // return nil 262 // } 263 // *nl = append(slice[:i], slice[i+1:]...) 264 // } 265 266 const nodeIDBits = 512 267 268 // NodeID is a unique identifier for each node. 269 // The node identifier is a marshaled elliptic curve public key. 270 type NodeID [nodeIDBits / 8]byte 271 272 // NodeID prints as a long hexadecimal number. 273 func (n NodeID) String() string { 274 return fmt.Sprintf("%x", n[:]) 275 } 276 277 // The Go syntax representation of a NodeID is a call to HexID. 278 func (n NodeID) GoString() string { 279 return fmt.Sprintf("discover.HexID(\"%x\")", n[:]) 280 } 281 282 // TerminalString returns a shortened hex string for terminal logging. 283 func (n NodeID) TerminalString() string { 284 return hex.EncodeToString(n[:8]) 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 (n NodeID) Pubkey() (*ecdsa.PublicKey, error) { 325 p := &ecdsa.PublicKey{Curve: ogcrypto.S256(), X: new(big.Int), Y: new(big.Int)} 326 half := len(n) / 2 327 p.X.SetBytes(n[:half]) 328 p.Y.SetBytes(n[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 func (id NodeID) mustPubkey() ecdsa.PublicKey { 336 pk, err := id.Pubkey() 337 if err != nil { 338 panic(err) 339 } 340 return *pk 341 } 342 343 // recoverNodeID computes the public key used to sign the 344 // given hash from the signature. 345 func recoverNodeID(hash, sig []byte) (id NodeID, err error) { 346 pubkey, err := ogcrypto.Ecrecover(hash, sig) 347 if err != nil { 348 return id, err 349 } 350 if len(pubkey)-1 != len(id) { 351 return id, fmt.Errorf("recovered pubkey has %d bits, want %d bits", len(pubkey)*8, (len(id)+1)*8) 352 } 353 for i := range id { 354 id[i] = pubkey[i+1] 355 } 356 return id, nil 357 } 358 359 // distcmp compares the distances a->target and b->target. 360 // Returns -1 if a is closer to target, 1 if b is closer to target 361 // and 0 if they are equal. 362 func distcmp(target, a, b types.Hash) int { 363 for i := range target.Bytes { 364 da := a.Bytes[i] ^ target.Bytes[i] 365 db := b.Bytes[i] ^ target.Bytes[i] 366 if da > db { 367 return 1 368 } else if da < db { 369 return -1 370 } 371 } 372 return 0 373 } 374 375 // table of leading zero counts for bytes [0..255] 376 var lzcount = [256]int{ 377 8, 7, 6, 6, 5, 5, 5, 5, 378 4, 4, 4, 4, 4, 4, 4, 4, 379 3, 3, 3, 3, 3, 3, 3, 3, 380 3, 3, 3, 3, 3, 3, 3, 3, 381 2, 2, 2, 2, 2, 2, 2, 2, 382 2, 2, 2, 2, 2, 2, 2, 2, 383 2, 2, 2, 2, 2, 2, 2, 2, 384 2, 2, 2, 2, 2, 2, 2, 2, 385 1, 1, 1, 1, 1, 1, 1, 1, 386 1, 1, 1, 1, 1, 1, 1, 1, 387 1, 1, 1, 1, 1, 1, 1, 1, 388 1, 1, 1, 1, 1, 1, 1, 1, 389 1, 1, 1, 1, 1, 1, 1, 1, 390 1, 1, 1, 1, 1, 1, 1, 1, 391 1, 1, 1, 1, 1, 1, 1, 1, 392 1, 1, 1, 1, 1, 1, 1, 1, 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 0, 0, 0, 0, 0, 0, 0, 0, 402 0, 0, 0, 0, 0, 0, 0, 0, 403 0, 0, 0, 0, 0, 0, 0, 0, 404 0, 0, 0, 0, 0, 0, 0, 0, 405 0, 0, 0, 0, 0, 0, 0, 0, 406 0, 0, 0, 0, 0, 0, 0, 0, 407 0, 0, 0, 0, 0, 0, 0, 0, 408 0, 0, 0, 0, 0, 0, 0, 0, 409 } 410 411 // logdist returns the logarithmic distance between a and b, log2(a ^ b). 412 func logdist(a, b types.Hash) int { 413 lz := 0 414 for i := range a.Bytes { 415 x := a.Bytes[i] ^ b.Bytes[i] 416 if x == 0 { 417 lz += 8 418 } else { 419 lz += lzcount[x] 420 break 421 } 422 } 423 return len(a.Bytes)*8 - lz 424 } 425 426 // hashAtDistance returns a random hash such that logdist(a, b) == n 427 func hashAtDistance(a types.Hash, n int) (b types.Hash) { 428 if n == 0 { 429 return a 430 } 431 // flip bit at position n, fill the rest with random bits 432 b = a 433 pos := len(a.Bytes) - n/8 - 1 434 bit := byte(0x01) << (byte(n%8) - 1) 435 if bit == 0 { 436 pos++ 437 bit = 0x80 438 } 439 b.Bytes[pos] = a.Bytes[pos]&^bit | ^a.Bytes[pos]&bit // TODO: randomize end bits 440 for i := pos + 1; i < len(a.Bytes); i++ { 441 b.Bytes[i] = byte(rand.Intn(255)) 442 } 443 return b 444 }