node.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. // Copyright 2018 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. package enode
  17. import (
  18. "crypto/ecdsa"
  19. "encoding/base64"
  20. "encoding/hex"
  21. "errors"
  22. "fmt"
  23. "math/bits"
  24. "math/rand"
  25. "net"
  26. "strings"
  27. "github.com/ethereum/go-ethereum/p2p/enr"
  28. "github.com/ethereum/go-ethereum/rlp"
  29. )
  30. var errMissingPrefix = errors.New("missing 'enr:' prefix for base64-encoded record")
  31. // Node represents a host on the network.
  32. type Node struct {
  33. r enr.Record
  34. id ID
  35. }
  36. // New wraps a node record. The record must be valid according to the given
  37. // identity scheme.
  38. func New(validSchemes enr.IdentityScheme, r *enr.Record) (*Node, error) {
  39. if err := r.VerifySignature(validSchemes); err != nil {
  40. return nil, err
  41. }
  42. node := &Node{r: *r}
  43. if n := copy(node.id[:], validSchemes.NodeAddr(&node.r)); n != len(ID{}) {
  44. return nil, fmt.Errorf("invalid node ID length %d, need %d", n, len(ID{}))
  45. }
  46. return node, nil
  47. }
  48. // MustParse parses a node record or enode:// URL. It panics if the input is invalid.
  49. func MustParse(rawurl string) *Node {
  50. n, err := Parse(ValidSchemes, rawurl)
  51. if err != nil {
  52. panic("invalid node: " + err.Error())
  53. }
  54. return n
  55. }
  56. // Parse decodes and verifies a base64-encoded node record.
  57. func Parse(validSchemes enr.IdentityScheme, input string) (*Node, error) {
  58. if strings.HasPrefix(input, "enode://") {
  59. return ParseV4(input)
  60. }
  61. if !strings.HasPrefix(input, "enr:") {
  62. return nil, errMissingPrefix
  63. }
  64. bin, err := base64.RawURLEncoding.DecodeString(input[4:])
  65. if err != nil {
  66. return nil, err
  67. }
  68. var r enr.Record
  69. if err := rlp.DecodeBytes(bin, &r); err != nil {
  70. return nil, err
  71. }
  72. return New(validSchemes, &r)
  73. }
  74. // ID returns the node identifier.
  75. func (n *Node) ID() ID {
  76. return n.id
  77. }
  78. // Seq returns the sequence number of the underlying record.
  79. func (n *Node) Seq() uint64 {
  80. return n.r.Seq()
  81. }
  82. // Incomplete returns true for nodes with no IP address.
  83. func (n *Node) Incomplete() bool {
  84. return n.IP() == nil
  85. }
  86. // Load retrieves an entry from the underlying record.
  87. func (n *Node) Load(k enr.Entry) error {
  88. return n.r.Load(k)
  89. }
  90. // IP returns the IP address of the node. This prefers IPv4 addresses.
  91. func (n *Node) IP() net.IP {
  92. var (
  93. ip4 enr.IPv4
  94. ip6 enr.IPv6
  95. )
  96. if n.Load(&ip4) == nil {
  97. return net.IP(ip4)
  98. }
  99. if n.Load(&ip6) == nil {
  100. return net.IP(ip6)
  101. }
  102. return nil
  103. }
  104. // UDP returns the UDP port of the node.
  105. func (n *Node) UDP() int {
  106. var port enr.UDP
  107. n.Load(&port)
  108. return int(port)
  109. }
  110. // UDP returns the TCP port of the node.
  111. func (n *Node) TCP() int {
  112. var port enr.TCP
  113. n.Load(&port)
  114. return int(port)
  115. }
  116. // Pubkey returns the secp256k1 public key of the node, if present.
  117. func (n *Node) Pubkey() *ecdsa.PublicKey {
  118. var key ecdsa.PublicKey
  119. if n.Load((*Secp256k1)(&key)) != nil {
  120. return nil
  121. }
  122. return &key
  123. }
  124. // Record returns the node's record. The return value is a copy and may
  125. // be modified by the caller.
  126. func (n *Node) Record() *enr.Record {
  127. cpy := n.r
  128. return &cpy
  129. }
  130. // ValidateComplete checks whether n has a valid IP and UDP port.
  131. // Deprecated: don't use this method.
  132. func (n *Node) ValidateComplete() error {
  133. if n.Incomplete() {
  134. return errors.New("missing IP address")
  135. }
  136. if n.UDP() == 0 {
  137. return errors.New("missing UDP port")
  138. }
  139. ip := n.IP()
  140. if ip.IsMulticast() || ip.IsUnspecified() {
  141. return errors.New("invalid IP (multicast/unspecified)")
  142. }
  143. // Validate the node key (on curve, etc.).
  144. var key Secp256k1
  145. return n.Load(&key)
  146. }
  147. // String returns the text representation of the record.
  148. func (n *Node) String() string {
  149. if isNewV4(n) {
  150. return n.URLv4() // backwards-compatibility glue for NewV4 nodes
  151. }
  152. enc, _ := rlp.EncodeToBytes(&n.r) // always succeeds because record is valid
  153. b64 := base64.RawURLEncoding.EncodeToString(enc)
  154. return "enr:" + b64
  155. }
  156. // MarshalText implements encoding.TextMarshaler.
  157. func (n *Node) MarshalText() ([]byte, error) {
  158. return []byte(n.String()), nil
  159. }
  160. // UnmarshalText implements encoding.TextUnmarshaler.
  161. func (n *Node) UnmarshalText(text []byte) error {
  162. dec, err := Parse(ValidSchemes, string(text))
  163. if err == nil {
  164. *n = *dec
  165. }
  166. return err
  167. }
  168. // ID is a unique identifier for each node.
  169. type ID [32]byte
  170. // Bytes returns a byte slice representation of the ID
  171. func (n ID) Bytes() []byte {
  172. return n[:]
  173. }
  174. // ID prints as a long hexadecimal number.
  175. func (n ID) String() string {
  176. return fmt.Sprintf("%x", n[:])
  177. }
  178. // The Go syntax representation of a ID is a call to HexID.
  179. func (n ID) GoString() string {
  180. return fmt.Sprintf("enode.HexID(\"%x\")", n[:])
  181. }
  182. // TerminalString returns a shortened hex string for terminal logging.
  183. func (n ID) TerminalString() string {
  184. return hex.EncodeToString(n[:8])
  185. }
  186. // MarshalText implements the encoding.TextMarshaler interface.
  187. func (n ID) MarshalText() ([]byte, error) {
  188. return []byte(hex.EncodeToString(n[:])), nil
  189. }
  190. // UnmarshalText implements the encoding.TextUnmarshaler interface.
  191. func (n *ID) UnmarshalText(text []byte) error {
  192. id, err := ParseID(string(text))
  193. if err != nil {
  194. return err
  195. }
  196. *n = id
  197. return nil
  198. }
  199. // HexID converts a hex string to an ID.
  200. // The string may be prefixed with 0x.
  201. // It panics if the string is not a valid ID.
  202. func HexID(in string) ID {
  203. id, err := ParseID(in)
  204. if err != nil {
  205. panic(err)
  206. }
  207. return id
  208. }
  209. func ParseID(in string) (ID, error) {
  210. var id ID
  211. b, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
  212. if err != nil {
  213. return id, err
  214. } else if len(b) != len(id) {
  215. return id, fmt.Errorf("wrong length, want %d hex chars", len(id)*2)
  216. }
  217. copy(id[:], b)
  218. return id, nil
  219. }
  220. // DistCmp compares the distances a->target and b->target.
  221. // Returns -1 if a is closer to target, 1 if b is closer to target
  222. // and 0 if they are equal.
  223. func DistCmp(target, a, b ID) int {
  224. for i := range target {
  225. da := a[i] ^ target[i]
  226. db := b[i] ^ target[i]
  227. if da > db {
  228. return 1
  229. } else if da < db {
  230. return -1
  231. }
  232. }
  233. return 0
  234. }
  235. // LogDist returns the logarithmic distance between a and b, log2(a ^ b).
  236. func LogDist(a, b ID) int {
  237. lz := 0
  238. for i := range a {
  239. x := a[i] ^ b[i]
  240. if x == 0 {
  241. lz += 8
  242. } else {
  243. lz += bits.LeadingZeros8(x)
  244. break
  245. }
  246. }
  247. return len(a)*8 - lz
  248. }
  249. // RandomID returns a random ID b such that logdist(a, b) == n.
  250. func RandomID(a ID, n int) (b ID) {
  251. if n == 0 {
  252. return a
  253. }
  254. // flip bit at position n, fill the rest with random bits
  255. b = a
  256. pos := len(a) - n/8 - 1
  257. bit := byte(0x01) << (byte(n%8) - 1)
  258. if bit == 0 {
  259. pos++
  260. bit = 0x80
  261. }
  262. b[pos] = a[pos]&^bit | ^a[pos]&bit // TODO: randomize end bits
  263. for i := pos + 1; i < len(a); i++ {
  264. b[i] = byte(rand.Intn(255))
  265. }
  266. return b
  267. }