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  }