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