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