github.com/quinndk/ethereum_read@v0.0.0-20181211143958-29c55eec3237/go-ethereum-master_read/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/ethereum/go-ethereum/common"
    35  	"github.com/ethereum/go-ethereum/crypto"
    36  	"github.com/ethereum/go-ethereum/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  // 节点表示网络上的主机
    44  type Node struct {
    45  	IP       net.IP // len 4 for IPv4 or 16 for IPv6
    46  	UDP, TCP uint16 // port numbers
    47  	ID       NodeID // the node's public key
    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  	// Time when the node was added to the table.
    57  	addedAt time.Time
    58  }
    59  
    60  // NewNode creates a new node. It is mostly meant to be used for
    61  // testing purposes.
    62  func NewNode(id NodeID, ip net.IP, udpPort, tcpPort uint16) *Node {
    63  	if ipv4 := ip.To4(); ipv4 != nil {
    64  		ip = ipv4
    65  	}
    66  	return &Node{
    67  		IP:  ip,
    68  		UDP: udpPort,
    69  		TCP: tcpPort,
    70  		ID:  id,
    71  		sha: crypto.Keccak256Hash(id[:]),
    72  	}
    73  }
    74  
    75  func (n *Node) addr() *net.UDPAddr {
    76  	return &net.UDPAddr{IP: n.IP, Port: int(n.UDP)}
    77  }
    78  
    79  // Incomplete returns true for nodes with no IP address.
    80  // 返回ip地址是否为空
    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  	return u.String()
   118  }
   119  
   120  var incompleteNodeURL = regexp.MustCompile("(?i)^(?:enode://)?([0-9a-f]+)$")
   121  
   122  // ParseNode parses a node designator.
   123  //
   124  // There are two basic forms of node designators
   125  //   - incomplete nodes, which only have the public key (node ID)
   126  //   - complete nodes, which contain the public key and IP/Port information
   127  //
   128  // For incomplete nodes, the designator must look like one of these
   129  //
   130  //    enode://<hex node id>
   131  //    <hex node id>
   132  //
   133  // For complete nodes, the node ID is encoded in the username portion
   134  // of the URL, separated from the host by an @ sign. The hostname can
   135  // only be given as an IP address, DNS domain names are not allowed.
   136  // The port in the host name section is the TCP listening port. If the
   137  // TCP and UDP (discovery) ports differ, the UDP port is specified as
   138  // query parameter "discport".
   139  //
   140  // In the following example, the node URL describes
   141  // a node with IP address 10.3.58.6, TCP listening port 30303
   142  // and UDP discovery port 30301.
   143  //
   144  //    enode://<hex node id>@10.3.58.6:30303?discport=30301
   145  func ParseNode(rawurl string) (*Node, error) {
   146  	if m := incompleteNodeURL.FindStringSubmatch(rawurl); m != nil {
   147  		id, err := HexID(m[1])
   148  		if err != nil {
   149  			return nil, fmt.Errorf("invalid node ID (%v)", err)
   150  		}
   151  		return NewNode(id, nil, 0, 0), nil
   152  	}
   153  	return parseComplete(rawurl)
   154  }
   155  
   156  func parseComplete(rawurl string) (*Node, error) {
   157  	var (
   158  		id               NodeID
   159  		ip               net.IP
   160  		tcpPort, udpPort uint64
   161  	)
   162  	u, err := url.Parse(rawurl)
   163  	if err != nil {
   164  		return nil, err
   165  	}
   166  	if u.Scheme != "enode" {
   167  		return nil, errors.New("invalid URL scheme, want \"enode\"")
   168  	}
   169  	// Parse the Node ID from the user portion.
   170  	if u.User == nil {
   171  		return nil, errors.New("does not contain node ID")
   172  	}
   173  	if id, err = HexID(u.User.String()); err != nil {
   174  		return nil, fmt.Errorf("invalid node ID (%v)", err)
   175  	}
   176  	// Parse the IP address.
   177  	host, port, err := net.SplitHostPort(u.Host)
   178  	if err != nil {
   179  		return nil, fmt.Errorf("invalid host: %v", err)
   180  	}
   181  	if ip = net.ParseIP(host); ip == nil {
   182  		return nil, errors.New("invalid IP address")
   183  	}
   184  	// Ensure the IP is 4 bytes long for IPv4 addresses.
   185  	if ipv4 := ip.To4(); ipv4 != nil {
   186  		ip = ipv4
   187  	}
   188  	// Parse the port numbers.
   189  	if tcpPort, err = strconv.ParseUint(port, 10, 16); err != nil {
   190  		return nil, errors.New("invalid port")
   191  	}
   192  	udpPort = tcpPort
   193  	qv := u.Query()
   194  	if qv.Get("discport") != "" {
   195  		udpPort, err = strconv.ParseUint(qv.Get("discport"), 10, 16)
   196  		if err != nil {
   197  			return nil, errors.New("invalid discport in query")
   198  		}
   199  	}
   200  	return NewNode(id, ip, uint16(udpPort), uint16(tcpPort)), nil
   201  }
   202  
   203  // MustParseNode parses a node URL. It panics if the URL is not valid.
   204  func MustParseNode(rawurl string) *Node {
   205  	n, err := ParseNode(rawurl)
   206  	if err != nil {
   207  		panic("invalid node URL: " + err.Error())
   208  	}
   209  	return n
   210  }
   211  
   212  // MarshalText implements encoding.TextMarshaler.
   213  func (n *Node) MarshalText() ([]byte, error) {
   214  	return []byte(n.String()), nil
   215  }
   216  
   217  // UnmarshalText implements encoding.TextUnmarshaler.
   218  func (n *Node) UnmarshalText(text []byte) error {
   219  	dec, err := ParseNode(string(text))
   220  	if err == nil {
   221  		*n = *dec
   222  	}
   223  	return err
   224  }
   225  
   226  // NodeID is a unique identifier for each node.
   227  // The node identifier is a marshaled elliptic curve public key.
   228  type NodeID [NodeIDBits / 8]byte
   229  
   230  // Bytes returns a byte slice representation of the NodeID
   231  func (n NodeID) Bytes() []byte {
   232  	return n[:]
   233  }
   234  
   235  // NodeID prints as a long hexadecimal number.
   236  func (n NodeID) String() string {
   237  	return fmt.Sprintf("%x", n[:])
   238  }
   239  
   240  // The Go syntax representation of a NodeID is a call to HexID.
   241  func (n NodeID) GoString() string {
   242  	return fmt.Sprintf("discover.HexID(\"%x\")", n[:])
   243  }
   244  
   245  // TerminalString returns a shortened hex string for terminal logging.
   246  func (n NodeID) TerminalString() string {
   247  	return hex.EncodeToString(n[:8])
   248  }
   249  
   250  // MarshalText implements the encoding.TextMarshaler interface.
   251  func (n NodeID) MarshalText() ([]byte, error) {
   252  	return []byte(hex.EncodeToString(n[:])), nil
   253  }
   254  
   255  // UnmarshalText implements the encoding.TextUnmarshaler interface.
   256  func (n *NodeID) UnmarshalText(text []byte) error {
   257  	id, err := HexID(string(text))
   258  	if err != nil {
   259  		return err
   260  	}
   261  	*n = id
   262  	return nil
   263  }
   264  
   265  // BytesID converts a byte slice to a NodeID
   266  func BytesID(b []byte) (NodeID, error) {
   267  	var id NodeID
   268  	if len(b) != len(id) {
   269  		return id, fmt.Errorf("wrong length, want %d bytes", len(id))
   270  	}
   271  	copy(id[:], b)
   272  	return id, nil
   273  }
   274  
   275  // MustBytesID converts a byte slice to a NodeID.
   276  // It panics if the byte slice is not a valid NodeID.
   277  func MustBytesID(b []byte) NodeID {
   278  	id, err := BytesID(b)
   279  	if err != nil {
   280  		panic(err)
   281  	}
   282  	return id
   283  }
   284  
   285  // HexID converts a hex string to a NodeID.
   286  // The string may be prefixed with 0x.
   287  func HexID(in string) (NodeID, error) {
   288  	var id NodeID
   289  	b, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
   290  	if err != nil {
   291  		return id, err
   292  	} else if len(b) != len(id) {
   293  		return id, fmt.Errorf("wrong length, want %d hex chars", len(id)*2)
   294  	}
   295  	copy(id[:], b)
   296  	return id, nil
   297  }
   298  
   299  // MustHexID converts a hex string to a NodeID.
   300  // It panics if the string is not a valid NodeID.
   301  func MustHexID(in string) NodeID {
   302  	id, err := HexID(in)
   303  	if err != nil {
   304  		panic(err)
   305  	}
   306  	return id
   307  }
   308  
   309  // PubkeyID returns a marshaled representation of the given public key.
   310  func PubkeyID(pub *ecdsa.PublicKey) NodeID {
   311  	var id NodeID
   312  	pbytes := elliptic.Marshal(pub.Curve, pub.X, pub.Y)
   313  	if len(pbytes)-1 != len(id) {
   314  		panic(fmt.Errorf("need %d bit pubkey, got %d bits", (len(id)+1)*8, len(pbytes)))
   315  	}
   316  	copy(id[:], pbytes[1:])
   317  	return id
   318  }
   319  
   320  // Pubkey returns the public key represented by the node ID.
   321  // It returns an error if the ID is not a point on the curve.
   322  func (id NodeID) Pubkey() (*ecdsa.PublicKey, error) {
   323  	p := &ecdsa.PublicKey{Curve: crypto.S256(), X: new(big.Int), Y: new(big.Int)}
   324  	half := len(id) / 2
   325  	p.X.SetBytes(id[:half])
   326  	p.Y.SetBytes(id[half:])
   327  	if !p.Curve.IsOnCurve(p.X, p.Y) {
   328  		return nil, errors.New("id is invalid secp256k1 curve point")
   329  	}
   330  	return p, nil
   331  }
   332  
   333  // recoverNodeID computes the public key used to sign the
   334  // given hash from the signature.
   335  func recoverNodeID(hash, sig []byte) (id NodeID, err error) {
   336  	pubkey, err := secp256k1.RecoverPubkey(hash, sig)
   337  	if err != nil {
   338  		return id, err
   339  	}
   340  	if len(pubkey)-1 != len(id) {
   341  		return id, fmt.Errorf("recovered pubkey has %d bits, want %d bits", len(pubkey)*8, (len(id)+1)*8)
   342  	}
   343  	for i := range id {
   344  		id[i] = pubkey[i+1]
   345  	}
   346  	return id, nil
   347  }
   348  
   349  // distcmp compares the distances a->target and b->target.
   350  // Returns -1 if a is closer to target, 1 if b is closer to target
   351  // and 0 if they are equal.
   352  func distcmp(target, a, b common.Hash) int {
   353  	for i := range target {
   354  		da := a[i] ^ target[i]
   355  		db := b[i] ^ target[i]
   356  		if da > db {
   357  			return 1
   358  		} else if da < db {
   359  			return -1
   360  		}
   361  	}
   362  	return 0
   363  }
   364  
   365  // table of leading zero counts for bytes [0..255]
   366  var lzcount = [256]int{
   367  	8, 7, 6, 6, 5, 5, 5, 5,
   368  	4, 4, 4, 4, 4, 4, 4, 4,
   369  	3, 3, 3, 3, 3, 3, 3, 3,
   370  	3, 3, 3, 3, 3, 3, 3, 3,
   371  	2, 2, 2, 2, 2, 2, 2, 2,
   372  	2, 2, 2, 2, 2, 2, 2, 2,
   373  	2, 2, 2, 2, 2, 2, 2, 2,
   374  	2, 2, 2, 2, 2, 2, 2, 2,
   375  	1, 1, 1, 1, 1, 1, 1, 1,
   376  	1, 1, 1, 1, 1, 1, 1, 1,
   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  	0, 0, 0, 0, 0, 0, 0, 0,
   384  	0, 0, 0, 0, 0, 0, 0, 0,
   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  }
   400  
   401  // logdist returns the logarithmic distance between a and b, log2(a ^ b).
   402  func logdist(a, b common.Hash) int {
   403  	lz := 0
   404  	for i := range a {
   405  		x := a[i] ^ b[i]
   406  		if x == 0 {
   407  			lz += 8
   408  		} else {
   409  			lz += lzcount[x]
   410  			break
   411  		}
   412  	}
   413  	return len(a)*8 - lz
   414  }
   415  
   416  // hashAtDistance returns a random hash such that logdist(a, b) == n
   417  func hashAtDistance(a common.Hash, n int) (b common.Hash) {
   418  	if n == 0 {
   419  		return a
   420  	}
   421  	// flip bit at position n, fill the rest with random bits
   422  	b = a
   423  	pos := len(a) - n/8 - 1
   424  	bit := byte(0x01) << (byte(n%8) - 1)
   425  	if bit == 0 {
   426  		pos++
   427  		bit = 0x80
   428  	}
   429  	b[pos] = a[pos]&^bit | ^a[pos]&bit // TODO: randomize end bits
   430  	for i := pos + 1; i < len(a); i++ {
   431  		b[i] = byte(rand.Intn(255))
   432  	}
   433  	return b
   434  }