github.com/oskarth/go-ethereum@v1.6.8-0.20191013093314-dac24a9d3494/p2p/discover/table_util_test.go (about)

     1  // Copyright 2015 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 discover
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"encoding/hex"
    22  	"fmt"
    23  	"math/rand"
    24  	"net"
    25  	"sync"
    26  
    27  	"github.com/ethereum/go-ethereum/p2p/enode"
    28  	"github.com/ethereum/go-ethereum/p2p/enr"
    29  )
    30  
    31  var nullNode *enode.Node
    32  
    33  func init() {
    34  	var r enr.Record
    35  	r.Set(enr.IP{0, 0, 0, 0})
    36  	nullNode = enode.SignNull(&r, enode.ID{})
    37  }
    38  
    39  func newTestTable(t transport) (*Table, *enode.DB) {
    40  	db, _ := enode.OpenDB("")
    41  	tab, _ := newTable(t, db, nil)
    42  	return tab, db
    43  }
    44  
    45  // nodeAtDistance creates a node for which enode.LogDist(base, n.id) == ld.
    46  func nodeAtDistance(base enode.ID, ld int, ip net.IP) *node {
    47  	var r enr.Record
    48  	r.Set(enr.IP(ip))
    49  	return wrapNode(enode.SignNull(&r, idAtDistance(base, ld)))
    50  }
    51  
    52  // idAtDistance returns a random hash such that enode.LogDist(a, b) == n
    53  func idAtDistance(a enode.ID, n int) (b enode.ID) {
    54  	if n == 0 {
    55  		return a
    56  	}
    57  	// flip bit at position n, fill the rest with random bits
    58  	b = a
    59  	pos := len(a) - n/8 - 1
    60  	bit := byte(0x01) << (byte(n%8) - 1)
    61  	if bit == 0 {
    62  		pos++
    63  		bit = 0x80
    64  	}
    65  	b[pos] = a[pos]&^bit | ^a[pos]&bit // TODO: randomize end bits
    66  	for i := pos + 1; i < len(a); i++ {
    67  		b[i] = byte(rand.Intn(255))
    68  	}
    69  	return b
    70  }
    71  
    72  func intIP(i int) net.IP {
    73  	return net.IP{byte(i), 0, 2, byte(i)}
    74  }
    75  
    76  // fillBucket inserts nodes into the given bucket until it is full.
    77  func fillBucket(tab *Table, n *node) (last *node) {
    78  	ld := enode.LogDist(tab.self().ID(), n.ID())
    79  	b := tab.bucket(n.ID())
    80  	for len(b.entries) < bucketSize {
    81  		b.entries = append(b.entries, nodeAtDistance(tab.self().ID(), ld, intIP(ld)))
    82  	}
    83  	return b.entries[bucketSize-1]
    84  }
    85  
    86  type pingRecorder struct {
    87  	mu           sync.Mutex
    88  	dead, pinged map[enode.ID]bool
    89  	n            *enode.Node
    90  }
    91  
    92  func newPingRecorder() *pingRecorder {
    93  	var r enr.Record
    94  	r.Set(enr.IP{0, 0, 0, 0})
    95  	n := enode.SignNull(&r, enode.ID{})
    96  
    97  	return &pingRecorder{
    98  		dead:   make(map[enode.ID]bool),
    99  		pinged: make(map[enode.ID]bool),
   100  		n:      n,
   101  	}
   102  }
   103  
   104  func (t *pingRecorder) self() *enode.Node {
   105  	return nullNode
   106  }
   107  
   108  func (t *pingRecorder) findnode(toid enode.ID, toaddr *net.UDPAddr, target encPubkey) ([]*node, error) {
   109  	return nil, nil
   110  }
   111  
   112  func (t *pingRecorder) waitping(from enode.ID) error {
   113  	return nil // remote always pings
   114  }
   115  
   116  func (t *pingRecorder) ping(toid enode.ID, toaddr *net.UDPAddr) error {
   117  	t.mu.Lock()
   118  	defer t.mu.Unlock()
   119  
   120  	t.pinged[toid] = true
   121  	if t.dead[toid] {
   122  		return errTimeout
   123  	} else {
   124  		return nil
   125  	}
   126  }
   127  
   128  func (t *pingRecorder) close() {}
   129  
   130  func hasDuplicates(slice []*node) bool {
   131  	seen := make(map[enode.ID]bool)
   132  	for i, e := range slice {
   133  		if e == nil {
   134  			panic(fmt.Sprintf("nil *Node at %d", i))
   135  		}
   136  		if seen[e.ID()] {
   137  			return true
   138  		}
   139  		seen[e.ID()] = true
   140  	}
   141  	return false
   142  }
   143  
   144  func contains(ns []*node, id enode.ID) bool {
   145  	for _, n := range ns {
   146  		if n.ID() == id {
   147  			return true
   148  		}
   149  	}
   150  	return false
   151  }
   152  
   153  func sortedByDistanceTo(distbase enode.ID, slice []*node) bool {
   154  	var last enode.ID
   155  	for i, e := range slice {
   156  		if i > 0 && enode.DistCmp(distbase, e.ID(), last) < 0 {
   157  			return false
   158  		}
   159  		last = e.ID()
   160  	}
   161  	return true
   162  }
   163  
   164  func hexEncPubkey(h string) (ret encPubkey) {
   165  	b, err := hex.DecodeString(h)
   166  	if err != nil {
   167  		panic(err)
   168  	}
   169  	if len(b) != len(ret) {
   170  		panic("invalid length")
   171  	}
   172  	copy(ret[:], b)
   173  	return ret
   174  }
   175  
   176  func hexPubkey(h string) *ecdsa.PublicKey {
   177  	k, err := decodePubkey(hexEncPubkey(h))
   178  	if err != nil {
   179  		panic(err)
   180  	}
   181  	return k
   182  }