node.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. package discover
  2. import (
  3. "crypto/ecdsa"
  4. "crypto/elliptic"
  5. "encoding/hex"
  6. "errors"
  7. "fmt"
  8. "io"
  9. "math/big"
  10. "math/rand"
  11. "net"
  12. "net/url"
  13. "strconv"
  14. "strings"
  15. "time"
  16. "github.com/ethereum/go-ethereum/crypto"
  17. "github.com/ethereum/go-ethereum/crypto/secp256k1"
  18. "github.com/ethereum/go-ethereum/rlp"
  19. )
  20. const nodeIDBits = 512
  21. // Node represents a host on the network.
  22. type Node struct {
  23. ID NodeID
  24. IP net.IP
  25. DiscPort int // UDP listening port for discovery protocol
  26. TCPPort int // TCP listening port for RLPx
  27. active time.Time
  28. }
  29. func newNode(id NodeID, addr *net.UDPAddr) *Node {
  30. return &Node{
  31. ID: id,
  32. IP: addr.IP,
  33. DiscPort: addr.Port,
  34. TCPPort: addr.Port,
  35. active: time.Now(),
  36. }
  37. }
  38. func (n *Node) isValid() bool {
  39. // TODO: don't accept localhost, LAN addresses from internet hosts
  40. return !n.IP.IsMulticast() && !n.IP.IsUnspecified() && n.TCPPort != 0 && n.DiscPort != 0
  41. }
  42. // The string representation of a Node is a URL.
  43. // Please see ParseNode for a description of the format.
  44. func (n *Node) String() string {
  45. addr := net.TCPAddr{IP: n.IP, Port: n.TCPPort}
  46. u := url.URL{
  47. Scheme: "enode",
  48. User: url.User(fmt.Sprintf("%x", n.ID[:])),
  49. Host: addr.String(),
  50. }
  51. if n.DiscPort != n.TCPPort {
  52. u.RawQuery = "discport=" + strconv.Itoa(n.DiscPort)
  53. }
  54. return u.String()
  55. }
  56. // ParseNode parses a node URL.
  57. //
  58. // A node URL has scheme "enode".
  59. //
  60. // The hexadecimal node ID is encoded in the username portion of the
  61. // URL, separated from the host by an @ sign. The hostname can only be
  62. // given as an IP address, DNS domain names are not allowed. The port
  63. // in the host name section is the TCP listening port. If the TCP and
  64. // UDP (discovery) ports differ, the UDP port is specified as query
  65. // parameter "discport".
  66. //
  67. // In the following example, the node URL describes
  68. // a node with IP address 10.3.58.6, TCP listening port 30303
  69. // and UDP discovery port 30301.
  70. //
  71. // enode://<hex node id>@10.3.58.6:30303?discport=30301
  72. func ParseNode(rawurl string) (*Node, error) {
  73. var n Node
  74. u, err := url.Parse(rawurl)
  75. if u.Scheme != "enode" {
  76. return nil, errors.New("invalid URL scheme, want \"enode\"")
  77. }
  78. if u.User == nil {
  79. return nil, errors.New("does not contain node ID")
  80. }
  81. if n.ID, err = HexID(u.User.String()); err != nil {
  82. return nil, fmt.Errorf("invalid node ID (%v)", err)
  83. }
  84. ip, port, err := net.SplitHostPort(u.Host)
  85. if err != nil {
  86. return nil, fmt.Errorf("invalid host: %v", err)
  87. }
  88. if n.IP = net.ParseIP(ip); n.IP == nil {
  89. return nil, errors.New("invalid IP address")
  90. }
  91. if n.TCPPort, err = strconv.Atoi(port); err != nil {
  92. return nil, errors.New("invalid port")
  93. }
  94. qv := u.Query()
  95. if qv.Get("discport") == "" {
  96. n.DiscPort = n.TCPPort
  97. } else {
  98. if n.DiscPort, err = strconv.Atoi(qv.Get("discport")); err != nil {
  99. return nil, errors.New("invalid discport in query")
  100. }
  101. }
  102. return &n, nil
  103. }
  104. // MustParseNode parses a node URL. It panics if the URL is not valid.
  105. func MustParseNode(rawurl string) *Node {
  106. n, err := ParseNode(rawurl)
  107. if err != nil {
  108. panic("invalid node URL: " + err.Error())
  109. }
  110. return n
  111. }
  112. func (n Node) EncodeRLP(w io.Writer) error {
  113. return rlp.Encode(w, rpcNode{IP: n.IP.String(), Port: uint16(n.TCPPort), ID: n.ID})
  114. }
  115. func (n *Node) DecodeRLP(s *rlp.Stream) (err error) {
  116. var ext rpcNode
  117. if err = s.Decode(&ext); err == nil {
  118. n.TCPPort = int(ext.Port)
  119. n.DiscPort = int(ext.Port)
  120. n.ID = ext.ID
  121. if n.IP = net.ParseIP(ext.IP); n.IP == nil {
  122. return errors.New("invalid IP string")
  123. }
  124. }
  125. return err
  126. }
  127. // NodeID is a unique identifier for each node.
  128. // The node identifier is a marshaled elliptic curve public key.
  129. type NodeID [nodeIDBits / 8]byte
  130. // NodeID prints as a long hexadecimal number.
  131. func (n NodeID) String() string {
  132. return fmt.Sprintf("%x", n[:])
  133. }
  134. // The Go syntax representation of a NodeID is a call to HexID.
  135. func (n NodeID) GoString() string {
  136. return fmt.Sprintf("discover.HexID(\"%x\")", n[:])
  137. }
  138. // HexID converts a hex string to a NodeID.
  139. // The string may be prefixed with 0x.
  140. func HexID(in string) (NodeID, error) {
  141. if strings.HasPrefix(in, "0x") {
  142. in = in[2:]
  143. }
  144. var id NodeID
  145. b, err := hex.DecodeString(in)
  146. if err != nil {
  147. return id, err
  148. } else if len(b) != len(id) {
  149. return id, fmt.Errorf("wrong length, need %d hex bytes", len(id))
  150. }
  151. copy(id[:], b)
  152. return id, nil
  153. }
  154. // MustHexID converts a hex string to a NodeID.
  155. // It panics if the string is not a valid NodeID.
  156. func MustHexID(in string) NodeID {
  157. id, err := HexID(in)
  158. if err != nil {
  159. panic(err)
  160. }
  161. return id
  162. }
  163. // PubkeyID returns a marshaled representation of the given public key.
  164. func PubkeyID(pub *ecdsa.PublicKey) NodeID {
  165. var id NodeID
  166. pbytes := elliptic.Marshal(pub.Curve, pub.X, pub.Y)
  167. if len(pbytes)-1 != len(id) {
  168. panic(fmt.Errorf("need %d bit pubkey, got %d bits", (len(id)+1)*8, len(pbytes)))
  169. }
  170. copy(id[:], pbytes[1:])
  171. return id
  172. }
  173. // Pubkey returns the public key represented by the node ID.
  174. // It returns an error if the ID is not a point on the curve.
  175. func (id NodeID) Pubkey() (*ecdsa.PublicKey, error) {
  176. p := &ecdsa.PublicKey{Curve: crypto.S256(), X: new(big.Int), Y: new(big.Int)}
  177. half := len(id) / 2
  178. p.X.SetBytes(id[:half])
  179. p.Y.SetBytes(id[half:])
  180. if !p.Curve.IsOnCurve(p.X, p.Y) {
  181. return nil, errors.New("not a point on the S256 curve")
  182. }
  183. return p, nil
  184. }
  185. // recoverNodeID computes the public key used to sign the
  186. // given hash from the signature.
  187. func recoverNodeID(hash, sig []byte) (id NodeID, err error) {
  188. pubkey, err := secp256k1.RecoverPubkey(hash, sig)
  189. if err != nil {
  190. return id, err
  191. }
  192. if len(pubkey)-1 != len(id) {
  193. return id, fmt.Errorf("recovered pubkey has %d bits, want %d bits", len(pubkey)*8, (len(id)+1)*8)
  194. }
  195. for i := range id {
  196. id[i] = pubkey[i+1]
  197. }
  198. return id, nil
  199. }
  200. // distcmp compares the distances a->target and b->target.
  201. // Returns -1 if a is closer to target, 1 if b is closer to target
  202. // and 0 if they are equal.
  203. func distcmp(target, a, b NodeID) int {
  204. for i := range target {
  205. da := a[i] ^ target[i]
  206. db := b[i] ^ target[i]
  207. if da > db {
  208. return 1
  209. } else if da < db {
  210. return -1
  211. }
  212. }
  213. return 0
  214. }
  215. // table of leading zero counts for bytes [0..255]
  216. var lzcount = [256]int{
  217. 8, 7, 6, 6, 5, 5, 5, 5,
  218. 4, 4, 4, 4, 4, 4, 4, 4,
  219. 3, 3, 3, 3, 3, 3, 3, 3,
  220. 3, 3, 3, 3, 3, 3, 3, 3,
  221. 2, 2, 2, 2, 2, 2, 2, 2,
  222. 2, 2, 2, 2, 2, 2, 2, 2,
  223. 2, 2, 2, 2, 2, 2, 2, 2,
  224. 2, 2, 2, 2, 2, 2, 2, 2,
  225. 1, 1, 1, 1, 1, 1, 1, 1,
  226. 1, 1, 1, 1, 1, 1, 1, 1,
  227. 1, 1, 1, 1, 1, 1, 1, 1,
  228. 1, 1, 1, 1, 1, 1, 1, 1,
  229. 1, 1, 1, 1, 1, 1, 1, 1,
  230. 1, 1, 1, 1, 1, 1, 1, 1,
  231. 1, 1, 1, 1, 1, 1, 1, 1,
  232. 1, 1, 1, 1, 1, 1, 1, 1,
  233. 0, 0, 0, 0, 0, 0, 0, 0,
  234. 0, 0, 0, 0, 0, 0, 0, 0,
  235. 0, 0, 0, 0, 0, 0, 0, 0,
  236. 0, 0, 0, 0, 0, 0, 0, 0,
  237. 0, 0, 0, 0, 0, 0, 0, 0,
  238. 0, 0, 0, 0, 0, 0, 0, 0,
  239. 0, 0, 0, 0, 0, 0, 0, 0,
  240. 0, 0, 0, 0, 0, 0, 0, 0,
  241. 0, 0, 0, 0, 0, 0, 0, 0,
  242. 0, 0, 0, 0, 0, 0, 0, 0,
  243. 0, 0, 0, 0, 0, 0, 0, 0,
  244. 0, 0, 0, 0, 0, 0, 0, 0,
  245. 0, 0, 0, 0, 0, 0, 0, 0,
  246. 0, 0, 0, 0, 0, 0, 0, 0,
  247. 0, 0, 0, 0, 0, 0, 0, 0,
  248. 0, 0, 0, 0, 0, 0, 0, 0,
  249. }
  250. // logdist returns the logarithmic distance between a and b, log2(a ^ b).
  251. func logdist(a, b NodeID) int {
  252. lz := 0
  253. for i := range a {
  254. x := a[i] ^ b[i]
  255. if x == 0 {
  256. lz += 8
  257. } else {
  258. lz += lzcount[x]
  259. break
  260. }
  261. }
  262. return len(a)*8 - lz
  263. }
  264. // randomID returns a random NodeID such that logdist(a, b) == n
  265. func randomID(a NodeID, n int) (b NodeID) {
  266. if n == 0 {
  267. return a
  268. }
  269. // flip bit at position n, fill the rest with random bits
  270. b = a
  271. pos := len(a) - n/8 - 1
  272. bit := byte(0x01) << (byte(n%8) - 1)
  273. if bit == 0 {
  274. pos++
  275. bit = 0x80
  276. }
  277. b[pos] = a[pos]&^bit | ^a[pos]&bit // TODO: randomize end bits
  278. for i := pos + 1; i < len(a); i++ {
  279. b[i] = byte(rand.Intn(255))
  280. }
  281. return b
  282. }