// Copyright 2015 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // The go-ethereum library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . package discover import ( "crypto/ecdsa" "errors" "math/big" "net" "time" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/secp256k1" "github.com/ethereum/go-ethereum/p2p/enode" ) // node represents a host on the network. // The fields of Node may not be modified. type node struct { enode.Node addedAt time.Time // time when the node was added to the table } type encPubkey [64]byte func encodePubkey(key *ecdsa.PublicKey) encPubkey { var e encPubkey math.ReadBits(key.X, e[:len(e)/2]) math.ReadBits(key.Y, e[len(e)/2:]) return e } func decodePubkey(e encPubkey) (*ecdsa.PublicKey, error) { p := &ecdsa.PublicKey{Curve: crypto.S256(), X: new(big.Int), Y: new(big.Int)} half := len(e) / 2 p.X.SetBytes(e[:half]) p.Y.SetBytes(e[half:]) if !p.Curve.IsOnCurve(p.X, p.Y) { return nil, errors.New("invalid secp256k1 curve point") } return p, nil } func (e encPubkey) id() enode.ID { return enode.ID(crypto.Keccak256Hash(e[:])) } // recoverNodeKey computes the public key used to sign the // given hash from the signature. func recoverNodeKey(hash, sig []byte) (key encPubkey, err error) { pubkey, err := secp256k1.RecoverPubkey(hash, sig) if err != nil { return key, err } copy(key[:], pubkey[1:]) return key, nil } func wrapNode(n *enode.Node) *node { return &node{Node: *n} } func wrapNodes(ns []*enode.Node) []*node { result := make([]*node, len(ns)) for i, n := range ns { result[i] = wrapNode(n) } return result } func unwrapNode(n *node) *enode.Node { return &n.Node } func unwrapNodes(ns []*node) []*enode.Node { result := make([]*enode.Node, len(ns)) for i, n := range ns { result[i] = unwrapNode(n) } return result } func (n *node) addr() *net.UDPAddr { return &net.UDPAddr{IP: n.IP(), Port: n.UDP()} } func (n *node) String() string { return n.Node.String() }