OSDN Git Service

Merge pull request #1051 from Bytom/fix_bug
[bytom/bytom-spv.git] / p2p / discover / node.go
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         "crypto/elliptic"
22         "encoding/hex"
23         "errors"
24         "fmt"
25         "math/rand"
26         "net"
27         "net/url"
28         "regexp"
29         "strconv"
30         "strings"
31
32         "github.com/bytom/common"
33         "github.com/bytom/crypto"
34 )
35
36 // Node represents a host on the network.
37 // The public fields of Node may not be modified.
38 type Node struct {
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
42
43         // Network-related fields are contained in nodeNetGuts.
44         // These fields are not supposed to be used off the
45         // Network.loop goroutine.
46         nodeNetGuts
47 }
48
49 // NewNode creates a new node. It is mostly meant to be used for
50 // testing purposes.
51 func NewNode(id NodeID, ip net.IP, udpPort, tcpPort uint16) *Node {
52         if ipv4 := ip.To4(); ipv4 != nil {
53                 ip = ipv4
54         }
55         return &Node{
56                 IP:          ip,
57                 UDP:         udpPort,
58                 TCP:         tcpPort,
59                 ID:          id,
60                 nodeNetGuts: nodeNetGuts{sha: crypto.Sha256Hash(id[:])},
61         }
62 }
63
64 func (n *Node) addr() *net.UDPAddr {
65         return &net.UDPAddr{IP: n.IP, Port: int(n.UDP)}
66 }
67
68 func (n *Node) setAddr(a *net.UDPAddr) {
69         n.IP = a.IP
70         if ipv4 := a.IP.To4(); ipv4 != nil {
71                 n.IP = ipv4
72         }
73         n.UDP = uint16(a.Port)
74 }
75
76 // compares the given address against the stored values.
77 func (n *Node) addrEqual(a *net.UDPAddr) bool {
78         ip := a.IP
79         if ipv4 := a.IP.To4(); ipv4 != nil {
80                 ip = ipv4
81         }
82         return n.UDP == uint16(a.Port) && n.IP.Equal(ip)
83 }
84
85 // Incomplete returns true for nodes with no IP address.
86 func (n *Node) Incomplete() bool {
87         return n.IP == nil
88 }
89
90 // checks whether n is a valid complete node.
91 func (n *Node) validateComplete() error {
92         if n.Incomplete() {
93                 return errors.New("incomplete node")
94         }
95         if n.UDP == 0 {
96                 return errors.New("missing UDP port")
97         }
98         if n.TCP == 0 {
99                 return errors.New("missing TCP port")
100         }
101         if n.IP.IsMulticast() || n.IP.IsUnspecified() {
102                 return errors.New("invalid IP (multicast/unspecified)")
103         }
104         //_, err := n.ID.Pubkey() // validate the key (on curve, etc.)
105         return nil
106 }
107
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"}
112         if n.Incomplete() {
113                 u.Host = fmt.Sprintf("%x", n.ID[:])
114         } else {
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()
118                 if n.UDP != n.TCP {
119                         u.RawQuery = "discport=" + strconv.Itoa(int(n.UDP))
120                 }
121         }
122         return u.String()
123 }
124
125 var incompleteNodeURL = regexp.MustCompile("(?i)^(?:enode://)?([0-9a-f]+)$")
126
127 // ParseNode parses a node designator.
128 //
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
132 //
133 // For incomplete nodes, the designator must look like one of these
134 //
135 //    enode://<hex node id>
136 //    <hex node id>
137 //
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".
144 //
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.
148 //
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])
153                 if err != nil {
154                         return nil, fmt.Errorf("invalid node ID (%v)", err)
155                 }
156                 return NewNode(id, nil, 0, 0), nil
157         }
158         return parseComplete(rawurl)
159 }
160
161 func parseComplete(rawurl string) (*Node, error) {
162         var (
163                 id               NodeID
164                 ip               net.IP
165                 tcpPort, udpPort uint64
166         )
167         u, err := url.Parse(rawurl)
168         if err != nil {
169                 return nil, err
170         }
171         if u.Scheme != "enode" {
172                 return nil, errors.New("invalid URL scheme, want \"enode\"")
173         }
174         // Parse the Node ID from the user portion.
175         if u.User == nil {
176                 return nil, errors.New("does not contain node ID")
177         }
178         if id, err = HexID(u.User.String()); err != nil {
179                 return nil, fmt.Errorf("invalid node ID (%v)", err)
180         }
181         // Parse the IP address.
182         host, port, err := net.SplitHostPort(u.Host)
183         if err != nil {
184                 return nil, fmt.Errorf("invalid host: %v", err)
185         }
186         if ip = net.ParseIP(host); ip == nil {
187                 return nil, errors.New("invalid IP address")
188         }
189         // Ensure the IP is 4 bytes long for IPv4 addresses.
190         if ipv4 := ip.To4(); ipv4 != nil {
191                 ip = ipv4
192         }
193         // Parse the port numbers.
194         if tcpPort, err = strconv.ParseUint(port, 10, 16); err != nil {
195                 return nil, errors.New("invalid port")
196         }
197         udpPort = tcpPort
198         qv := u.Query()
199         if qv.Get("discport") != "" {
200                 udpPort, err = strconv.ParseUint(qv.Get("discport"), 10, 16)
201                 if err != nil {
202                         return nil, errors.New("invalid discport in query")
203                 }
204         }
205         return NewNode(id, ip, uint16(udpPort), uint16(tcpPort)), nil
206 }
207
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)
211         if err != nil {
212                 panic("invalid node URL: " + err.Error())
213         }
214         return n
215 }
216
217 // MarshalText implements encoding.TextMarshaler.
218 func (n *Node) MarshalText() ([]byte, error) {
219         return []byte(n.String()), nil
220 }
221
222 // UnmarshalText implements encoding.TextUnmarshaler.
223 func (n *Node) UnmarshalText(text []byte) error {
224         dec, err := ParseNode(string(text))
225         if err == nil {
226                 *n = *dec
227         }
228         return err
229 }
230
231 // type nodeQueue []*Node
232 //
233 // // pushNew adds n to the end if it is not present.
234 // func (nl *nodeList) appendNew(n *Node) {
235 //      for _, entry := range n {
236 //              if entry == n {
237 //                      return
238 //              }
239 //      }
240 //      *nq = append(*nq, n)
241 // }
242 //
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)
249 // }
250 //
251 // func (nl *nodeList) removeIndex(i int) *Node {
252 //      slice = *nl
253 //      if len(*slice) <= i {
254 //              return nil
255 //      }
256 //      *nl = append(slice[:i], slice[i+1:]...)
257 // }
258
259 const nodeIDBits = 32
260
261 // NodeID is a unique identifier for each node.
262 // The node identifier is a marshaled elliptic curve public key.
263 type NodeID [32]byte
264
265 // NodeID prints as a long hexadecimal number.
266 func (n NodeID) String() string {
267         return fmt.Sprintf("%x", n[:])
268 }
269
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[:])
273 }
274
275 // TerminalString returns a shortened hex string for terminal logging.
276 func (n NodeID) TerminalString() string {
277         return hex.EncodeToString(n[:8])
278 }
279
280 // HexID converts a hex string to a NodeID.
281 // The string may be prefixed with 0x.
282 func HexID(in string) (NodeID, error) {
283         var id NodeID
284         b, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
285         if err != nil {
286                 return id, err
287         } else if len(b) != len(id) {
288                 return id, fmt.Errorf("wrong length, want %d hex chars", len(id)*2)
289         }
290         copy(id[:], b)
291         return id, nil
292 }
293
294 // ByteID converts a []byte to a NodeID.
295 func ByteID(in []byte) NodeID {
296         var id NodeID
297         for i := range id {
298                 id[i] = in[i]
299         }
300         return id
301 }
302
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 {
306         id, err := HexID(in)
307         if err != nil {
308                 panic(err)
309         }
310         return id
311 }
312
313 // PubkeyID returns a marshaled representation of the given public key.
314 func PubkeyID(pub *ecdsa.PublicKey) NodeID {
315         var id 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)))
319         }
320         copy(id[:], pbytes[1:])
321         return id
322 }
323
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")
333 //      }
334 //      return p, nil
335 //}
336
337 //func (id NodeID) mustPubkey() ecdsa.PublicKey {
338 //      pk, err := id.Pubkey()
339 //      if err != nil {
340 //              panic(err)
341 //      }
342 //      return *pk
343 //}
344
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)
349 //      if err != nil {
350 //              return id, err
351 //      }
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)
354 //      }
355 //      for i := range id {
356 //              id[i] = pubkey[i+1]
357 //      }
358 //      return id, nil
359 //}
360
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]
368                 if da > db {
369                         return 1
370                 } else if da < db {
371                         return -1
372                 }
373         }
374         return 0
375 }
376
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,
411 }
412
413 // logdist returns the logarithmic distance between a and b, log2(a ^ b).
414 func logdist(a, b common.Hash) int {
415         lz := 0
416         for i := range a {
417                 x := a[i] ^ b[i]
418                 if x == 0 {
419                         lz += 8
420                 } else {
421                         lz += lzcount[x]
422                         break
423                 }
424         }
425         return len(a)*8 - lz
426 }
427
428 // hashAtDistance returns a random hash such that logdist(a, b) == n
429 func hashAtDistance(a common.Hash, n int) (b common.Hash) {
430         if n == 0 {
431                 return a
432         }
433         // flip bit at position n, fill the rest with random bits
434         b = a
435         pos := len(a) - n/8 - 1
436         bit := byte(0x01) << (byte(n%8) - 1)
437         if bit == 0 {
438                 pos++
439                 bit = 0x80
440         }
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))
444         }
445         return b
446 }