1 // Copyright 2015 The go-ethereum Authors
2 // This file is part of the go-ethereum library.
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.
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.
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/>.
32 "github.com/bytom/common"
33 "github.com/bytom/crypto"
36 // Node represents a host on the network.
37 // The public fields of Node may not be modified.
39 IP net.IP // len 4 for IPv4 or 16 for IPv6
40 UDP, TCP uint16 // port numbers
41 ID NodeID // the node's public key
43 // Network-related fields are contained in nodeNetGuts.
44 // These fields are not supposed to be used off the
45 // Network.loop goroutine.
49 // NewNode creates a new node. It is mostly meant to be used for
51 func NewNode(id NodeID, ip net.IP, udpPort, tcpPort uint16) *Node {
52 if ipv4 := ip.To4(); ipv4 != nil {
60 nodeNetGuts: nodeNetGuts{sha: crypto.Sha256Hash(id[:])},
64 func (n *Node) addr() *net.UDPAddr {
65 return &net.UDPAddr{IP: n.IP, Port: int(n.UDP)}
68 func (n *Node) setAddr(a *net.UDPAddr) {
70 if ipv4 := a.IP.To4(); ipv4 != nil {
73 n.UDP = uint16(a.Port)
76 // compares the given address against the stored values.
77 func (n *Node) addrEqual(a *net.UDPAddr) bool {
79 if ipv4 := a.IP.To4(); ipv4 != nil {
82 return n.UDP == uint16(a.Port) && n.IP.Equal(ip)
85 // Incomplete returns true for nodes with no IP address.
86 func (n *Node) Incomplete() bool {
90 // checks whether n is a valid complete node.
91 func (n *Node) validateComplete() error {
93 return errors.New("incomplete node")
96 return errors.New("missing UDP port")
99 return errors.New("missing TCP port")
101 if n.IP.IsMulticast() || n.IP.IsUnspecified() {
102 return errors.New("invalid IP (multicast/unspecified)")
104 //_, err := n.ID.Pubkey() // validate the key (on curve, etc.)
108 // The string representation of a Node is a URL.
109 // Please see ParseNode for a description of the format.
110 func (n *Node) String() string {
111 u := url.URL{Scheme: "enode"}
113 u.Host = fmt.Sprintf("%x", n.ID[:])
115 addr := net.TCPAddr{IP: n.IP, Port: int(n.TCP)}
116 u.User = url.User(fmt.Sprintf("%x", n.ID[:]))
117 u.Host = addr.String()
119 u.RawQuery = "discport=" + strconv.Itoa(int(n.UDP))
125 var incompleteNodeURL = regexp.MustCompile("(?i)^(?:enode://)?([0-9a-f]+)$")
127 // ParseNode parses a node designator.
129 // There are two basic forms of node designators
130 // - incomplete nodes, which only have the public key (node ID)
131 // - complete nodes, which contain the public key and IP/Port information
133 // For incomplete nodes, the designator must look like one of these
135 // enode://<hex node id>
138 // For complete nodes, the node ID is encoded in the username portion
139 // of the URL, separated from the host by an @ sign. The hostname can
140 // only be given as an IP address, DNS domain names are not allowed.
141 // The port in the host name section is the TCP listening port. If the
142 // TCP and UDP (discovery) ports differ, the UDP port is specified as
143 // query parameter "discport".
145 // In the following example, the node URL describes
146 // a node with IP address 10.3.58.6, TCP listening port 30303
147 // and UDP discovery port 30301.
149 // enode://<hex node id>@10.3.58.6:30303?discport=30301
150 func ParseNode(rawurl string) (*Node, error) {
151 if m := incompleteNodeURL.FindStringSubmatch(rawurl); m != nil {
152 id, err := HexID(m[1])
154 return nil, fmt.Errorf("invalid node ID (%v)", err)
156 return NewNode(id, nil, 0, 0), nil
158 return parseComplete(rawurl)
161 func parseComplete(rawurl string) (*Node, error) {
165 tcpPort, udpPort uint64
167 u, err := url.Parse(rawurl)
171 if u.Scheme != "enode" {
172 return nil, errors.New("invalid URL scheme, want \"enode\"")
174 // Parse the Node ID from the user portion.
176 return nil, errors.New("does not contain node ID")
178 if id, err = HexID(u.User.String()); err != nil {
179 return nil, fmt.Errorf("invalid node ID (%v)", err)
181 // Parse the IP address.
182 host, port, err := net.SplitHostPort(u.Host)
184 return nil, fmt.Errorf("invalid host: %v", err)
186 if ip = net.ParseIP(host); ip == nil {
187 return nil, errors.New("invalid IP address")
189 // Ensure the IP is 4 bytes long for IPv4 addresses.
190 if ipv4 := ip.To4(); ipv4 != nil {
193 // Parse the port numbers.
194 if tcpPort, err = strconv.ParseUint(port, 10, 16); err != nil {
195 return nil, errors.New("invalid port")
199 if qv.Get("discport") != "" {
200 udpPort, err = strconv.ParseUint(qv.Get("discport"), 10, 16)
202 return nil, errors.New("invalid discport in query")
205 return NewNode(id, ip, uint16(udpPort), uint16(tcpPort)), nil
208 // MustParseNode parses a node URL. It panics if the URL is not valid.
209 func MustParseNode(rawurl string) *Node {
210 n, err := ParseNode(rawurl)
212 panic("invalid node URL: " + err.Error())
217 // MarshalText implements encoding.TextMarshaler.
218 func (n *Node) MarshalText() ([]byte, error) {
219 return []byte(n.String()), nil
222 // UnmarshalText implements encoding.TextUnmarshaler.
223 func (n *Node) UnmarshalText(text []byte) error {
224 dec, err := ParseNode(string(text))
231 // type nodeQueue []*Node
233 // // pushNew adds n to the end if it is not present.
234 // func (nl *nodeList) appendNew(n *Node) {
235 // for _, entry := range n {
240 // *nq = append(*nq, n)
243 // // popRandom removes a random node. Nodes closer to
244 // // to the head of the beginning of the have a slightly higher probability.
245 // func (nl *nodeList) popRandom() *Node {
246 // ix := rand.Intn(len(*nq))
247 // //TODO: probability as mentioned above.
248 // nl.removeIndex(ix)
251 // func (nl *nodeList) removeIndex(i int) *Node {
253 // if len(*slice) <= i {
256 // *nl = append(slice[:i], slice[i+1:]...)
259 const nodeIDBits = 32
261 // NodeID is a unique identifier for each node.
262 // The node identifier is a marshaled elliptic curve public key.
265 // NodeID prints as a long hexadecimal number.
266 func (n NodeID) String() string {
267 return fmt.Sprintf("%x", n[:])
270 // The Go syntax representation of a NodeID is a call to HexID.
271 func (n NodeID) GoString() string {
272 return fmt.Sprintf("discover.HexID(\"%x\")", n[:])
275 // TerminalString returns a shortened hex string for terminal logging.
276 func (n NodeID) TerminalString() string {
277 return hex.EncodeToString(n[:8])
280 // HexID converts a hex string to a NodeID.
281 // The string may be prefixed with 0x.
282 func HexID(in string) (NodeID, error) {
284 b, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
287 } else if len(b) != len(id) {
288 return id, fmt.Errorf("wrong length, want %d hex chars", len(id)*2)
294 // ByteID converts a []byte to a NodeID.
295 func ByteID(in []byte) NodeID {
303 // MustHexID converts a hex string to a NodeID.
304 // It panics if the string is not a valid NodeID.
305 func MustHexID(in string) NodeID {
313 // PubkeyID returns a marshaled representation of the given public key.
314 func PubkeyID(pub *ecdsa.PublicKey) NodeID {
316 pbytes := elliptic.Marshal(pub.Curve, pub.X, pub.Y)
317 if len(pbytes)-1 != len(id) {
318 panic(fmt.Errorf("need %d bit pubkey, got %d bits", (len(id)+1)*8, len(pbytes)))
320 copy(id[:], pbytes[1:])
324 //// Pubkey returns the public key represented by the node ID.
325 ////// It returns an error if the ID is not a point on the curve.
326 //func (id NodeID) Pubkey() (*ecdsa.PublicKey, error) {
327 // p := &ecdsa.PublicKey{Curve: crypto.S256(), X: new(big.Int), Y: new(big.Int)}
328 // half := len(id) / 2
329 // p.X.SetBytes(id[:half])
330 // p.Y.SetBytes(id[half:])
331 // if !p.Curve.IsOnCurve(p.X, p.Y) {
332 // return nil, errors.New("id is invalid secp256k1 curve point")
337 //func (id NodeID) mustPubkey() ecdsa.PublicKey {
338 // pk, err := id.Pubkey()
345 // recoverNodeID computes the public key used to sign the
346 // given hash from the signature.
347 //func recoverNodeID(hash, sig []byte) (id NodeID, err error) {
348 // pubkey, err := crypto.Ecrecover(hash, sig)
352 // if len(pubkey)-1 != len(id) {
353 // return id, fmt.Errorf("recovered pubkey has %d bits, want %d bits", len(pubkey)*8, (len(id)+1)*8)
355 // for i := range id {
356 // id[i] = pubkey[i+1]
361 // distcmp compares the distances a->target and b->target.
362 // Returns -1 if a is closer to target, 1 if b is closer to target
363 // and 0 if they are equal.
364 func distcmp(target, a, b common.Hash) int {
365 for i := range target {
366 da := a[i] ^ target[i]
367 db := b[i] ^ target[i]
377 // table of leading zero counts for bytes [0..255]
378 var lzcount = [256]int{
379 8, 7, 6, 6, 5, 5, 5, 5,
380 4, 4, 4, 4, 4, 4, 4, 4,
381 3, 3, 3, 3, 3, 3, 3, 3,
382 3, 3, 3, 3, 3, 3, 3, 3,
383 2, 2, 2, 2, 2, 2, 2, 2,
384 2, 2, 2, 2, 2, 2, 2, 2,
385 2, 2, 2, 2, 2, 2, 2, 2,
386 2, 2, 2, 2, 2, 2, 2, 2,
387 1, 1, 1, 1, 1, 1, 1, 1,
388 1, 1, 1, 1, 1, 1, 1, 1,
389 1, 1, 1, 1, 1, 1, 1, 1,
390 1, 1, 1, 1, 1, 1, 1, 1,
391 1, 1, 1, 1, 1, 1, 1, 1,
392 1, 1, 1, 1, 1, 1, 1, 1,
393 1, 1, 1, 1, 1, 1, 1, 1,
394 1, 1, 1, 1, 1, 1, 1, 1,
395 0, 0, 0, 0, 0, 0, 0, 0,
396 0, 0, 0, 0, 0, 0, 0, 0,
397 0, 0, 0, 0, 0, 0, 0, 0,
398 0, 0, 0, 0, 0, 0, 0, 0,
399 0, 0, 0, 0, 0, 0, 0, 0,
400 0, 0, 0, 0, 0, 0, 0, 0,
401 0, 0, 0, 0, 0, 0, 0, 0,
402 0, 0, 0, 0, 0, 0, 0, 0,
403 0, 0, 0, 0, 0, 0, 0, 0,
404 0, 0, 0, 0, 0, 0, 0, 0,
405 0, 0, 0, 0, 0, 0, 0, 0,
406 0, 0, 0, 0, 0, 0, 0, 0,
407 0, 0, 0, 0, 0, 0, 0, 0,
408 0, 0, 0, 0, 0, 0, 0, 0,
409 0, 0, 0, 0, 0, 0, 0, 0,
410 0, 0, 0, 0, 0, 0, 0, 0,
413 // logdist returns the logarithmic distance between a and b, log2(a ^ b).
414 func logdist(a, b common.Hash) int {
428 // hashAtDistance returns a random hash such that logdist(a, b) == n
429 func hashAtDistance(a common.Hash, n int) (b common.Hash) {
433 // flip bit at position n, fill the rest with random bits
435 pos := len(a) - n/8 - 1
436 bit := byte(0x01) << (byte(n%8) - 1)
441 b[pos] = a[pos]&^bit | ^a[pos]&bit // TODO: randomize end bits
442 for i := pos + 1; i < len(a); i++ {
443 b[i] = byte(rand.Intn(255))