github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/p2p/enode/node.go (about)

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