Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion eth/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func EthProtocol(txPool txPool, chainManager chainManager, blockPool blockPool)
// the main loop that handles incoming messages
// note RemovePeer in the post-disconnect hook
func runEthProtocol(txPool txPool, chainManager chainManager, blockPool blockPool, peer *p2p.Peer, rw p2p.MsgReadWriter) (err error) {
id := peer.ID()
id := peer.PublicKey()
self := &ethProtocol{
txPool: txPool,
chainManager: chainManager,
Expand Down
13 changes: 6 additions & 7 deletions p2p/crypto.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package p2p

import (
// "binary"
"crypto/ecdsa"
"crypto/rand"
"fmt"
Expand Down Expand Up @@ -37,26 +36,26 @@ func (self hexkey) String() string {
}

func encHandshake(conn io.ReadWriter, prv *ecdsa.PrivateKey, dial *discover.Node) (
remoteID discover.NodeID,
remotePublicKey discover.PublicKey,
sessionToken []byte,
err error,
) {
if dial == nil {
var remotePubkey []byte
sessionToken, remotePubkey, err = inboundEncHandshake(conn, prv, nil)
copy(remoteID[:], remotePubkey)
copy(remotePublicKey[:], remotePubkey)
} else {
remoteID = dial.ID
sessionToken, err = outboundEncHandshake(conn, prv, remoteID[:], nil)
remotePublicKey = dial.PublicKey
sessionToken, err = outboundEncHandshake(conn, prv, remotePublicKey[:], nil)
}
return remoteID, sessionToken, err
return remotePublicKey, sessionToken, err
}

// outboundEncHandshake negotiates a session token on conn.
// it should be called on the dialing side of the connection.
//
// privateKey is the local client's private key
// remotePublicKey is the remote peer's node ID
// remotePublicKey is the remote peer's node PublicKey
// sessionToken is the token from a previous session with this node.
func outboundEncHandshake(conn io.ReadWriter, prvKey *ecdsa.PrivateKey, remotePublicKey []byte, sessionToken []byte) (
newSessionToken []byte,
Expand Down
94 changes: 57 additions & 37 deletions p2p/discover/node.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package discover

import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"encoding/hex"
Expand All @@ -14,33 +15,51 @@ import (
"strings"
"time"

ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/ethereum/go-ethereum/rlp"
)

const nodeIDBits = 512
const (
PublicKeyBits = 512
idBits = 256
)

var (
hashfunc = crypto.SHA256
// idSize = hashfunc.Size()
)

type NodeID [idBits / 8]byte

// Node represents a host on the network.
type Node struct {
ID NodeID
IP net.IP
PublicKey PublicKey
IP net.IP
NodeID NodeID

DiscPort int // UDP listening port for discovery protocol
TCPPort int // TCP listening port for RLPx

active time.Time
}

func newNode(id NodeID, addr *net.UDPAddr) *Node {
func newNode(pubkey PublicKey, id NodeID, addr *net.UDPAddr) *Node {
return &Node{
ID: id,
IP: addr.IP,
DiscPort: addr.Port,
TCPPort: addr.Port,
active: time.Now(),
PublicKey: pubkey,
IP: addr.IP,
DiscPort: addr.Port,
TCPPort: addr.Port,
active: time.Now(),
NodeID: id,
}
}

func Hash(id PublicKey) (a NodeID) {
copy(a[:], ethcrypto.Sha256(id[:]))
return
}

func (n *Node) isValid() bool {
// TODO: don't accept localhost, LAN addresses from internet hosts
return !n.IP.IsMulticast() && !n.IP.IsUnspecified() && n.TCPPort != 0 && n.DiscPort != 0
Expand All @@ -52,7 +71,7 @@ func (n *Node) String() string {
addr := net.TCPAddr{IP: n.IP, Port: n.TCPPort}
u := url.URL{
Scheme: "enode",
User: url.User(fmt.Sprintf("%x", n.ID[:])),
User: url.User(fmt.Sprintf("%x", n.PublicKey[:])),
Host: addr.String(),
}
if n.DiscPort != n.TCPPort {
Expand All @@ -65,7 +84,7 @@ func (n *Node) String() string {
//
// A node URL has scheme "enode".
//
// The hexadecimal node ID is encoded in the username portion of the
// The hexadecimal node PublicKey is encoded in the username portion of the
// URL, separated from the host by an @ sign. The hostname can only be
// given as an IP address, DNS domain names are not allowed. The port
// in the host name section is the TCP listening port. If the TCP and
Expand All @@ -84,11 +103,12 @@ func ParseNode(rawurl string) (*Node, error) {
return nil, errors.New("invalid URL scheme, want \"enode\"")
}
if u.User == nil {
return nil, errors.New("does not contain node ID")
return nil, errors.New("does not contain node PublicKey")
}
if n.ID, err = HexID(u.User.String()); err != nil {
return nil, fmt.Errorf("invalid node ID (%v)", err)
if n.PublicKey, err = HexPublicKey(u.User.String()); err != nil {
return nil, fmt.Errorf("invalid node PublicKey (%v)", err)
}
n.NodeID = Hash(n.PublicKey)
ip, port, err := net.SplitHostPort(u.Host)
if err != nil {
return nil, fmt.Errorf("invalid host: %v", err)
Expand Down Expand Up @@ -120,42 +140,42 @@ func MustParseNode(rawurl string) *Node {
}

func (n Node) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, rpcNode{IP: n.IP.String(), Port: uint16(n.TCPPort), ID: n.ID})
return rlp.Encode(w, rpcNode{IP: n.IP.String(), Port: uint16(n.TCPPort), PublicKey: n.PublicKey})
}
func (n *Node) DecodeRLP(s *rlp.Stream) (err error) {
var ext rpcNode
if err = s.Decode(&ext); err == nil {
n.TCPPort = int(ext.Port)
n.DiscPort = int(ext.Port)
n.ID = ext.ID
n.PublicKey = ext.PublicKey
if n.IP = net.ParseIP(ext.IP); n.IP == nil {
return errors.New("invalid IP string")
}
}
return err
}

// NodeID is a unique identifier for each node.
// PublicKey is a unique identifier for each node.
// The node identifier is a marshaled elliptic curve public key.
type NodeID [nodeIDBits / 8]byte
type PublicKey [PublicKeyBits / 8]byte

// NodeID prints as a long hexadecimal number.
func (n NodeID) String() string {
// PublicKey prints as a long hexadecimal number.
func (n PublicKey) 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("discover.HexID(\"%#x\")", n[:])
// The Go syntax representation of a PublicKey is a call to HexPublicKey.
func (n PublicKey) GoString() string {
return fmt.Sprintf("discover.HexPublicKey(\"%#x\")", n[:])
}

// HexID converts a hex string to a NodeID.
// HexPublicKey converts a hex string to a PublicKey.
// The string may be prefixed with 0x.
func HexID(in string) (NodeID, error) {
func HexPublicKey(in string) (PublicKey, error) {
if strings.HasPrefix(in, "0x") {
in = in[2:]
}
var id NodeID
var id PublicKey
b, err := hex.DecodeString(in)
if err != nil {
return id, err
Expand All @@ -166,19 +186,19 @@ func HexID(in string) (NodeID, error) {
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)
// MustHexPublicKey converts a hex string to a PublicKey.
// It panics if the string is not a valid PublicKey.
func MustHexPublicKey(in string) PublicKey {
id, err := HexPublicKey(in)
if err != nil {
panic(err)
}
return id
}

// PubkeyID returns a marshaled representation of the given public key.
func PubkeyID(pub *ecdsa.PublicKey) NodeID {
var id NodeID
// PublicKey returns a marshaled representation of the given public key.
func exportPublicKey(pub *ecdsa.PublicKey) PublicKey {
var id PublicKey
pbytes := elliptic.Marshal(pub.Curve, pub.X, pub.Y)
if len(pbytes)-1 != len(id) {
panic(fmt.Errorf("need %d bit pubkey, got %d bits", (len(id)+1)*8, len(pbytes)))
Expand All @@ -187,9 +207,9 @@ func PubkeyID(pub *ecdsa.PublicKey) NodeID {
return id
}

// recoverNodeID computes the public key used to sign the
// recoverPublicKey computes the public key used to sign the
// given hash from the signature.
func recoverNodeID(hash, sig []byte) (id NodeID, err error) {
func recoverPublicKey(hash, sig []byte) (id PublicKey, err error) {
pubkey, err := secp256k1.RecoverPubkey(hash, sig)
if err != nil {
return id, err
Expand Down Expand Up @@ -270,8 +290,8 @@ func logdist(a, b NodeID) int {
return len(a)*8 - lz
}

// randomID returns a random NodeID such that logdist(a, b) == n
func randomID(a NodeID, n int) (b NodeID) {
// randomNodeID returns a random NodeID such that logdist(a, b) == n
func randomNodeID(a NodeID, n int) (b NodeID) {
if n == 0 {
return a
}
Expand Down
Loading