aboutsummaryrefslogtreecommitdiffstats
path: root/p2p/discover/table.go
diff options
context:
space:
mode:
authorFelix Lange <fjl@twurst.com>2015-02-06 21:40:53 +0800
committerFelix Lange <fjl@twurst.com>2015-02-07 07:12:23 +0800
commit8564eb9f7efcc7a0e639f6a45d7e67037fedac5f (patch)
tree2b2ebde612d7d084b87b3eff9b6db0e08ea552ed /p2p/discover/table.go
parent56f777b2fc77275bc636562b66a08b19afe2ec56 (diff)
downloaddexon-8564eb9f7efcc7a0e639f6a45d7e67037fedac5f.tar.gz
dexon-8564eb9f7efcc7a0e639f6a45d7e67037fedac5f.tar.zst
dexon-8564eb9f7efcc7a0e639f6a45d7e67037fedac5f.zip
p2p/discover: add node URL functions, distinguish TCP/UDP ports
The discovery RPC protocol does not yet distinguish TCP and UDP ports. But it can't hurt to do so in our internal model.
Diffstat (limited to 'p2p/discover/table.go')
-rw-r--r--p2p/discover/table.go197
1 files changed, 4 insertions, 193 deletions
diff --git a/p2p/discover/table.go b/p2p/discover/table.go
index ea9680404..6025507eb 100644
--- a/p2p/discover/table.go
+++ b/p2p/discover/table.go
@@ -7,20 +7,10 @@
package discover
import (
- "crypto/ecdsa"
- "crypto/elliptic"
- "encoding/hex"
- "fmt"
- "io"
- "math/rand"
"net"
"sort"
- "strings"
"sync"
"time"
-
- "github.com/ethereum/go-ethereum/crypto/secp256k1"
- "github.com/ethereum/go-ethereum/rlp"
)
const (
@@ -53,36 +43,10 @@ type bucket struct {
entries []*Node
}
-// Node represents node metadata that is stored in the table.
-type Node struct {
- Addr *net.UDPAddr
- ID NodeID
-
- active time.Time
-}
-
-type rpcNode struct {
- IP string
- Port uint16
- ID NodeID
-}
-
-func (n Node) EncodeRLP(w io.Writer) error {
- return rlp.Encode(w, rpcNode{IP: n.Addr.IP.String(), Port: uint16(n.Addr.Port), ID: n.ID})
-}
-func (n *Node) DecodeRLP(s *rlp.Stream) (err error) {
- var ext rpcNode
- if err = s.Decode(&ext); err == nil {
- n.Addr = &net.UDPAddr{IP: net.ParseIP(ext.IP), Port: int(ext.Port)}
- n.ID = ext.ID
- }
- return err
-}
-
func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr) *Table {
- tab := &Table{net: t, self: &Node{ID: ourID, Addr: ourAddr}}
+ tab := &Table{net: t, self: newNode(ourID, ourAddr)}
for i := range tab.buckets {
- tab.buckets[i] = &bucket{}
+ tab.buckets[i] = new(bucket)
}
return tab
}
@@ -217,7 +181,7 @@ func (tab *Table) len() (n int) {
func (tab *Table) bumpOrAdd(node NodeID, from *net.UDPAddr) (n *Node) {
b := tab.buckets[logdist(tab.self.ID, node)]
if n = b.bump(node); n == nil {
- n = &Node{ID: node, Addr: from, active: time.Now()}
+ n = newNode(node, from)
if len(b.entries) == bucketSize {
tab.pingReplace(n, b)
} else {
@@ -238,6 +202,7 @@ func (tab *Table) pingReplace(n *Node, b *bucket) {
tab.mutex.Lock()
if len(b.entries) > 0 && b.entries[len(b.entries)-1] == old {
// slide down other entries and put the new one in front.
+ // TODO: insert in correct position to keep the order
copy(b.entries[1:], b.entries)
b.entries[0] = n
}
@@ -312,157 +277,3 @@ func (h *nodesByDistance) push(n *Node, maxElems int) {
h.entries[ix] = n
}
}
-
-// NodeID is a unique identifier for each node.
-// The node identifier is a marshaled elliptic curve public key.
-type NodeID [512 / 8]byte
-
-// NodeID prints as a long hexadecimal number.
-func (n NodeID) String() string {
- return fmt.Sprintf("%#x", n[:])
-}
-
-// The Go syntax representation of a NodeID is a call to HexID.
-func (n NodeID) GoString() string {
- return fmt.Sprintf("HexID(\"%#x\")", n[:])
-}
-
-// HexID converts a hex string to a NodeID.
-// The string may be prefixed with 0x.
-func HexID(in string) (NodeID, error) {
- if strings.HasPrefix(in, "0x") {
- in = in[2:]
- }
- var id NodeID
- b, err := hex.DecodeString(in)
- if err != nil {
- return id, err
- } else if len(b) != len(id) {
- return id, fmt.Errorf("wrong length, need %d hex bytes", len(id))
- }
- copy(id[:], b)
- return id, nil
-}
-
-// MustHexID converts a hex string to a NodeID.
-// It panics if the string is not a valid NodeID.
-func MustHexID(in string) NodeID {
- id, err := HexID(in)
- if err != nil {
- panic(err)
- }
- return id
-}
-
-func PubkeyID(pub *ecdsa.PublicKey) NodeID {
- var id NodeID
- pbytes := elliptic.Marshal(pub.Curve, pub.X, pub.Y)
- if len(pbytes)-1 != len(id) {
- panic(fmt.Errorf("invalid key: need %d bit pubkey, got %d bits", (len(id)+1)*8, len(pbytes)))
- }
- copy(id[:], pbytes[1:])
- return id
-}
-
-// recoverNodeID computes the public key used to sign the
-// given hash from the signature.
-func recoverNodeID(hash, sig []byte) (id NodeID, err error) {
- pubkey, err := secp256k1.RecoverPubkey(hash, sig)
- if err != nil {
- return id, err
- }
- if len(pubkey)-1 != len(id) {
- return id, fmt.Errorf("recovered pubkey has %d bits, want %d bits", len(pubkey)*8, (len(id)+1)*8)
- }
- for i := range id {
- id[i] = pubkey[i+1]
- }
- return id, nil
-}
-
-// distcmp compares the distances a->target and b->target.
-// Returns -1 if a is closer to target, 1 if b is closer to target
-// and 0 if they are equal.
-func distcmp(target, a, b NodeID) int {
- for i := range target {
- da := a[i] ^ target[i]
- db := b[i] ^ target[i]
- if da > db {
- return 1
- } else if da < db {
- return -1
- }
- }
- return 0
-}
-
-// table of leading zero counts for bytes [0..255]
-var lzcount = [256]int{
- 8, 7, 6, 6, 5, 5, 5, 5,
- 4, 4, 4, 4, 4, 4, 4, 4,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-}
-
-// logdist returns the logarithmic distance between a and b, log2(a ^ b).
-func logdist(a, b NodeID) int {
- lz := 0
- for i := range a {
- x := a[i] ^ b[i]
- if x == 0 {
- lz += 8
- } else {
- lz += lzcount[x]
- break
- }
- }
- return len(a)*8 - lz
-}
-
-// randomID returns a random NodeID such that logdist(a, b) == n
-func randomID(a NodeID, n int) (b NodeID) {
- if n == 0 {
- return a
- }
- // flip bit at position n, fill the rest with random bits
- b = a
- pos := len(a) - n/8 - 1
- bit := byte(0x01) << (byte(n%8) - 1)
- if bit == 0 {
- pos++
- bit = 0x80
- }
- b[pos] = a[pos]&^bit | ^a[pos]&bit // TODO: randomize end bits
- for i := pos + 1; i < len(a); i++ {
- b[i] = byte(rand.Intn(255))
- }
- return b
-}