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