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