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