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  }