github.com/insight-chain/inb-go@v1.1.3-0.20191221022159-da049980ae38/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/insight-chain/inb-go/common"
    25  	"math/bits"
    26  	"math/rand"
    27  	"net"
    28  	"strings"
    29  
    30  	"github.com/insight-chain/inb-go/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  	var ip net.IP
    75  	n.Load((*enr.IP)(&ip))
    76  	return ip
    77  }
    78  
    79  // UDP returns the UDP port of the node.
    80  func (n *Node) UDP() int {
    81  	var port enr.UDP
    82  	n.Load(&port)
    83  	return int(port)
    84  }
    85  
    86  // UDP returns the TCP port of the node.
    87  func (n *Node) TCP() int {
    88  	var port enr.TCP
    89  	n.Load(&port)
    90  	return int(port)
    91  }
    92  
    93  // Pubkey returns the secp256k1 public key of the node, if present.
    94  func (n *Node) Pubkey() *ecdsa.PublicKey {
    95  	var key ecdsa.PublicKey
    96  	if n.Load((*Secp256k1)(&key)) != nil {
    97  		return nil
    98  	}
    99  	return &key
   100  }
   101  
   102  // Record returns the node's record. The return value is a copy and may
   103  // be modified by the caller.
   104  func (n *Node) Record() *enr.Record {
   105  	cpy := n.r
   106  	return &cpy
   107  }
   108  
   109  // checks whether n is a valid complete node.
   110  func (n *Node) ValidateComplete() error {
   111  	if n.Incomplete() {
   112  		return errors.New("incomplete node")
   113  	}
   114  	if n.UDP() == 0 {
   115  		return errors.New("missing UDP port")
   116  	}
   117  	ip := n.IP()
   118  	if ip.IsMulticast() || ip.IsUnspecified() {
   119  		return errors.New("invalid IP (multicast/unspecified)")
   120  	}
   121  	// Validate the node key (on curve, etc.).
   122  	var key Secp256k1
   123  	return n.Load(&key)
   124  }
   125  
   126  // The string representation of a Node is a URL.
   127  // Please see ParseNode for a description of the format.
   128  func (n *Node) String() string {
   129  	return n.v4URL()
   130  }
   131  
   132  // MarshalText implements encoding.TextMarshaler.
   133  func (n *Node) MarshalText() ([]byte, error) {
   134  	return []byte(n.v4URL()), nil
   135  }
   136  
   137  // UnmarshalText implements encoding.TextUnmarshaler.
   138  func (n *Node) UnmarshalText(text []byte) error {
   139  	dec, err := ParseV4(string(text))
   140  	if err == nil {
   141  		*n = *dec
   142  	}
   143  	return err
   144  }
   145  // is equals node
   146  func (n *Node) Equals(id string) bool {
   147  	if common.IsEmpty(id) {
   148  		return false
   149  	}
   150  	//TODO Test This is not very good
   151  	contains := strings.Contains(n.v4URL(), id)
   152  	return contains
   153  }
   154  
   155  // ID is a unique identifier for each node.
   156  type ID [32]byte
   157  
   158  // Bytes returns a byte slice representation of the ID
   159  func (n ID) Bytes() []byte {
   160  	return n[:]
   161  }
   162  
   163  // ID prints as a long hexadecimal number.
   164  func (n ID) String() string {
   165  	return fmt.Sprintf("%x", n[:])
   166  }
   167  
   168  // The Go syntax representation of a ID is a call to HexID.
   169  func (n ID) GoString() string {
   170  	return fmt.Sprintf("enode.HexID(\"%x\")", n[:])
   171  }
   172  
   173  // TerminalString returns a shortened hex string for terminal logging.
   174  func (n ID) TerminalString() string {
   175  	return hex.EncodeToString(n[:8])
   176  }
   177  
   178  // MarshalText implements the encoding.TextMarshaler interface.
   179  func (n ID) MarshalText() ([]byte, error) {
   180  	return []byte(hex.EncodeToString(n[:])), nil
   181  }
   182  
   183  // UnmarshalText implements the encoding.TextUnmarshaler interface.
   184  func (n *ID) UnmarshalText(text []byte) error {
   185  	id, err := parseID(string(text))
   186  	if err != nil {
   187  		return err
   188  	}
   189  	*n = id
   190  	return nil
   191  }
   192  
   193  // HexID converts a hex string to an ID.
   194  // The string may be prefixed with 0x.
   195  // It panics if the string is not a valid ID.
   196  func HexID(in string) ID {
   197  	id, err := parseID(in)
   198  	if err != nil {
   199  		panic(err)
   200  	}
   201  	return id
   202  }
   203  
   204  func parseID(in string) (ID, error) {
   205  	var id ID
   206  	b, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
   207  	if err != nil {
   208  		return id, err
   209  	} else if len(b) != len(id) {
   210  		return id, fmt.Errorf("wrong length, want %d hex chars", len(id)*2)
   211  	}
   212  	copy(id[:], b)
   213  	return id, nil
   214  }
   215  
   216  // DistCmp compares the distances a->target and b->target.
   217  // Returns -1 if a is closer to target, 1 if b is closer to target
   218  // and 0 if they are equal.
   219  func DistCmp(target, a, b ID) int {
   220  	for i := range target {
   221  		da := a[i] ^ target[i]
   222  		db := b[i] ^ target[i]
   223  		if da > db {
   224  			return 1
   225  		} else if da < db {
   226  			return -1
   227  		}
   228  	}
   229  	return 0
   230  }
   231  
   232  // LogDist returns the logarithmic distance between a and b, log2(a ^ b).
   233  func LogDist(a, b ID) int {
   234  	lz := 0
   235  	for i := range a {
   236  		x := a[i] ^ b[i]
   237  		if x == 0 {
   238  			lz += 8
   239  		} else {
   240  			lz += bits.LeadingZeros8(x)
   241  			break
   242  		}
   243  	}
   244  	return len(a)*8 - lz
   245  }
   246  
   247  // RandomID returns a random ID b such that logdist(a, b) == n.
   248  func RandomID(a ID, n int) (b ID) {
   249  	if n == 0 {
   250  		return a
   251  	}
   252  	// flip bit at position n, fill the rest with random bits
   253  	b = a
   254  	pos := len(a) - n/8 - 1
   255  	bit := byte(0x01) << (byte(n%8) - 1)
   256  	if bit == 0 {
   257  		pos++
   258  		bit = 0x80
   259  	}
   260  	b[pos] = a[pos]&^bit | ^a[pos]&bit // TODO: randomize end bits
   261  	for i := pos + 1; i < len(a); i++ {
   262  		b[i] = byte(rand.Intn(255))
   263  	}
   264  	return b
   265  }