github.com/hyperion-hyn/go-ethereum@v2.4.0+incompatible/p2p/enode/node.go (about)

     1  // Copyright 2018 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 enode
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"encoding/hex"
    22  	"errors"
    23  	"fmt"
    24  	"github.com/ethereum/go-ethereum/log"
    25  	"math/bits"
    26  	"math/rand"
    27  	"net"
    28  	"strings"
    29  
    30  	"github.com/ethereum/go-ethereum/p2p/enr"
    31  )
    32  
    33  // Node represents a host on the network.
    34  type Node struct {
    35  	r  enr.Record
    36  	id ID
    37  }
    38  
    39  // New wraps a node record. The record must be valid according to the given
    40  // identity scheme.
    41  func New(validSchemes enr.IdentityScheme, r *enr.Record) (*Node, error) {
    42  	if err := r.VerifySignature(validSchemes); err != nil {
    43  		return nil, err
    44  	}
    45  	node := &Node{r: *r}
    46  	if n := copy(node.id[:], validSchemes.NodeAddr(&node.r)); n != len(ID{}) {
    47  		return nil, fmt.Errorf("invalid node ID length %d, need %d", n, len(ID{}))
    48  	}
    49  	return node, nil
    50  }
    51  
    52  // ID returns the node identifier.
    53  func (n *Node) ID() ID {
    54  	return n.id
    55  }
    56  
    57  // Seq returns the sequence number of the underlying record.
    58  func (n *Node) Seq() uint64 {
    59  	return n.r.Seq()
    60  }
    61  
    62  // Incomplete returns true for nodes with no IP address.
    63  func (n *Node) Incomplete() bool {
    64  	return n.IP() == nil
    65  }
    66  
    67  // Load retrieves an entry from the underlying record.
    68  func (n *Node) Load(k enr.Entry) error {
    69  	return n.r.Load(k)
    70  }
    71  
    72  // IP returns the IP address of the node.
    73  func (n *Node) IP() net.IP {
    74  	// QUORUM
    75  	// no host is set, so use the IP directly
    76  	if n.Host() == "" {
    77  		return n.loadIP()
    78  	}
    79  	// attempt to look up IP addresses if host is a FQDN
    80  	lookupIPs, err := net.LookupIP(n.Host())
    81  	if err != nil {
    82  		log.Debug("hostname couldn't resolve, using IP instead", "hostname", n.Host(), "err", err.Error())
    83  		return n.loadIP()
    84  	}
    85  	// set to first ip by default
    86  	return lookupIPs[0]
    87  	// END QUORUM
    88  }
    89  
    90  func (n *Node) loadIP() net.IP {
    91  	var ip net.IP
    92  	n.Load((*enr.IP)(&ip))
    93  	return ip
    94  }
    95  
    96  // Quorum
    97  func (n *Node) Host() string {
    98  	var hostname string
    99  	n.Load((*enr.Hostname)(&hostname))
   100  	return hostname
   101  }
   102  // End-Quorum
   103  
   104  // UDP returns the UDP port of the node.
   105  func (n *Node) UDP() int {
   106  	var port enr.UDP
   107  	n.Load(&port)
   108  	return int(port)
   109  }
   110  
   111  // used by Quorum RAFT - returns the Raft port of the node
   112  func (n *Node) RaftPort() int {
   113  	var port enr.RaftPort
   114  	err := n.Load(&port)
   115  	if err != nil {
   116  		return 0
   117  	}
   118  	return int(port)
   119  }
   120  
   121  func (n *Node) HasRaftPort() bool {
   122  	return n.RaftPort() > 0
   123  }
   124  
   125  // UDP returns the TCP port of the node.
   126  func (n *Node) TCP() int {
   127  	var port enr.TCP
   128  	n.Load(&port)
   129  	return int(port)
   130  }
   131  
   132  // Pubkey returns the secp256k1 public key of the node, if present.
   133  func (n *Node) Pubkey() *ecdsa.PublicKey {
   134  	var key ecdsa.PublicKey
   135  	if n.Load((*Secp256k1)(&key)) != nil {
   136  		return nil
   137  	}
   138  	return &key
   139  }
   140  
   141  // Record returns the node's record. The return value is a copy and may
   142  // be modified by the caller.
   143  func (n *Node) Record() *enr.Record {
   144  	cpy := n.r
   145  	return &cpy
   146  }
   147  
   148  // checks whether n is a valid complete node.
   149  func (n *Node) ValidateComplete() error {
   150  	if n.Incomplete() {
   151  		return errors.New("incomplete node")
   152  	}
   153  	if n.UDP() == 0 {
   154  		return errors.New("missing UDP port")
   155  	}
   156  	ip := n.IP()
   157  	if ip.IsMulticast() || ip.IsUnspecified() {
   158  		return errors.New("invalid IP (multicast/unspecified)")
   159  	}
   160  	// Validate the node key (on curve, etc.).
   161  	var key Secp256k1
   162  	return n.Load(&key)
   163  }
   164  
   165  // The string representation of a Node is a URL.
   166  // Please see ParseNode for a description of the format.
   167  func (n *Node) String() string {
   168  	return n.v4URL()
   169  }
   170  
   171  // MarshalText implements encoding.TextMarshaler.
   172  func (n *Node) MarshalText() ([]byte, error) {
   173  	return []byte(n.v4URL()), nil
   174  }
   175  
   176  // UnmarshalText implements encoding.TextUnmarshaler.
   177  func (n *Node) UnmarshalText(text []byte) error {
   178  	dec, err := ParseV4(string(text))
   179  	if err == nil {
   180  		*n = *dec
   181  	}
   182  	return err
   183  }
   184  
   185  // ID is a unique identifier for each node.
   186  type ID [32]byte
   187  
   188  // Bytes returns a byte slice representation of the ID
   189  func (n ID) Bytes() []byte {
   190  	return n[:]
   191  }
   192  
   193  // ID prints as a long hexadecimal number.
   194  func (n ID) String() string {
   195  	return fmt.Sprintf("%x", n[:])
   196  }
   197  
   198  // The Go syntax representation of a ID is a call to HexID.
   199  func (n ID) GoString() string {
   200  	return fmt.Sprintf("enode.HexID(\"%x\")", n[:])
   201  }
   202  
   203  // TerminalString returns a shortened hex string for terminal logging.
   204  func (n ID) TerminalString() string {
   205  	return hex.EncodeToString(n[:8])
   206  }
   207  
   208  // MarshalText implements the encoding.TextMarshaler interface.
   209  func (n ID) MarshalText() ([]byte, error) {
   210  	return []byte(hex.EncodeToString(n[:])), nil
   211  }
   212  
   213  // UnmarshalText implements the encoding.TextUnmarshaler interface.
   214  func (n *ID) UnmarshalText(text []byte) error {
   215  	id, err := parseID(string(text))
   216  	if err != nil {
   217  		return err
   218  	}
   219  	*n = id
   220  	return nil
   221  }
   222  
   223  // ID is a unique identifier for each node used by RAFT
   224  type EnodeID [64]byte
   225  
   226  // ID prints as a long hexadecimal number.
   227  func (n EnodeID) String() string {
   228  	return fmt.Sprintf("%x", n[:])
   229  }
   230  
   231  // The Go syntax representation of a ID is a call to HexID.
   232  func (n EnodeID) GoString() string {
   233  	return fmt.Sprintf("enode.HexID(\"%x\")", n[:])
   234  }
   235  
   236  // MarshalText implements the encoding.TextMarshaler interface.
   237  func (n EnodeID) MarshalText() ([]byte, error) {
   238  	return []byte(hex.EncodeToString(n[:])), nil
   239  }
   240  
   241  // UnmarshalText implements the encoding.TextUnmarshaler interface.
   242  func (n *EnodeID) UnmarshalText(text []byte) error {
   243  	id, err := RaftHexID(string(text))
   244  	if err != nil {
   245  		return err
   246  	}
   247  	*n = id
   248  	return nil
   249  }
   250  
   251  // HexID converts a hex string to an ID.
   252  // The string may be prefixed with 0x.
   253  // It panics if the string is not a valid ID.
   254  func HexID(in string) ID {
   255  	id, err := parseID(in)
   256  	if err != nil {
   257  		panic(err)
   258  	}
   259  	return id
   260  }
   261  
   262  // used by Quorum RAFT to derive 64 byte nodeId from 128 byte enodeID
   263  func RaftHexID(in string) (EnodeID, error) {
   264  	var id EnodeID
   265  	b, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
   266  	if err != nil {
   267  		return id, err
   268  	} else if len(b) != len(id) {
   269  		return id, fmt.Errorf("wrong length, want %d hex chars", len(id)*2)
   270  	}
   271  
   272  	copy(id[:], b)
   273  	return id, nil
   274  }
   275  
   276  func parseID(in string) (ID, error) {
   277  	var id ID
   278  	b, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
   279  	if err != nil {
   280  		return id, err
   281  	} else if len(b) != len(id) {
   282  		return id, fmt.Errorf("wrong length, want %d hex chars", len(id)*2)
   283  	}
   284  	copy(id[:], b)
   285  	return id, nil
   286  }
   287  
   288  // DistCmp compares the distances a->target and b->target.
   289  // Returns -1 if a is closer to target, 1 if b is closer to target
   290  // and 0 if they are equal.
   291  func DistCmp(target, a, b ID) int {
   292  	for i := range target {
   293  		da := a[i] ^ target[i]
   294  		db := b[i] ^ target[i]
   295  		if da > db {
   296  			return 1
   297  		} else if da < db {
   298  			return -1
   299  		}
   300  	}
   301  	return 0
   302  }
   303  
   304  // LogDist returns the logarithmic distance between a and b, log2(a ^ b).
   305  func LogDist(a, b ID) int {
   306  	lz := 0
   307  	for i := range a {
   308  		x := a[i] ^ b[i]
   309  		if x == 0 {
   310  			lz += 8
   311  		} else {
   312  			lz += bits.LeadingZeros8(x)
   313  			break
   314  		}
   315  	}
   316  	return len(a)*8 - lz
   317  }
   318  
   319  // RandomID returns a random ID b such that logdist(a, b) == n.
   320  func RandomID(a ID, n int) (b ID) {
   321  	if n == 0 {
   322  		return a
   323  	}
   324  	// flip bit at position n, fill the rest with random bits
   325  	b = a
   326  	pos := len(a) - n/8 - 1
   327  	bit := byte(0x01) << (byte(n%8) - 1)
   328  	if bit == 0 {
   329  		pos++
   330  		bit = 0x80
   331  	}
   332  	b[pos] = a[pos]&^bit | ^a[pos]&bit // TODO: randomize end bits
   333  	for i := pos + 1; i < len(a); i++ {
   334  		b[i] = byte(rand.Intn(255))
   335  	}
   336  	return b
   337  }