node.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  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. "net"
  25. "strings"
  26. "github.com/ethereum/go-ethereum/p2p/enr"
  27. "github.com/ethereum/go-ethereum/rlp"
  28. )
  29. var errMissingPrefix = errors.New("missing 'enr:' prefix for base64-encoded record")
  30. // Node represents a host on the network.
  31. type Node struct {
  32. r enr.Record
  33. id ID
  34. }
  35. // New wraps a node record. The record must be valid according to the given
  36. // identity scheme.
  37. func New(validSchemes enr.IdentityScheme, r *enr.Record) (*Node, error) {
  38. if err := r.VerifySignature(validSchemes); err != nil {
  39. return nil, err
  40. }
  41. node := &Node{r: *r}
  42. if n := copy(node.id[:], validSchemes.NodeAddr(&node.r)); n != len(ID{}) {
  43. return nil, fmt.Errorf("invalid node ID length %d, need %d", n, len(ID{}))
  44. }
  45. return node, nil
  46. }
  47. // MustParse parses a node record or enode:// URL. It panics if the input is invalid.
  48. func MustParse(rawurl string) *Node {
  49. n, err := Parse(ValidSchemes, rawurl)
  50. if err != nil {
  51. panic("invalid node: " + err.Error())
  52. }
  53. return n
  54. }
  55. // Parse decodes and verifies a base64-encoded node record.
  56. func Parse(validSchemes enr.IdentityScheme, input string) (*Node, error) {
  57. if strings.HasPrefix(input, "enode://") {
  58. return ParseV4(input)
  59. }
  60. if !strings.HasPrefix(input, "enr:") {
  61. return nil, errMissingPrefix
  62. }
  63. bin, err := base64.RawURLEncoding.DecodeString(input[4:])
  64. if err != nil {
  65. return nil, err
  66. }
  67. var r enr.Record
  68. if err := rlp.DecodeBytes(bin, &r); err != nil {
  69. return nil, err
  70. }
  71. return New(validSchemes, &r)
  72. }
  73. // ID returns the node identifier.
  74. func (n *Node) ID() ID {
  75. return n.id
  76. }
  77. // Seq returns the sequence number of the underlying record.
  78. func (n *Node) Seq() uint64 {
  79. return n.r.Seq()
  80. }
  81. // Quorum
  82. // Incomplete returns true for nodes with no IP address and no hostname if with raftport.
  83. func (n *Node) Incomplete() bool {
  84. return n.IP() == nil && (!n.HasRaftPort() || (n.Host() == "" && n.HasRaftPort()))
  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.
  91. //
  92. // Quorum
  93. // To support DNS lookup in node ip. The function performs hostname lookup if hostname is defined in enr.Hostname
  94. // and falls back to enr.IP value in case of failure. It also makes sure the resolved IP is in IPv4 or IPv6 format
  95. func (n *Node) IP() net.IP {
  96. if n.Host() == "" {
  97. // no host is set, so use the IP directly
  98. return n.loadIP()
  99. }
  100. // attempt to look up IP addresses if host is a FQDN
  101. lookupIPs, err := net.LookupIP(n.Host())
  102. if err != nil {
  103. return n.loadIP()
  104. }
  105. // set to first ip by default & as Ethereum upstream
  106. ip := lookupIPs[0]
  107. // Ensure the IP is 4 bytes long for IPv4 addresses.
  108. if ipv4 := ip.To4(); ipv4 != nil {
  109. ip = ipv4
  110. }
  111. return ip
  112. }
  113. func (n *Node) loadIP() net.IP {
  114. var (
  115. ip4 enr.IPv4
  116. ip6 enr.IPv6
  117. )
  118. if n.Load(&ip4) == nil {
  119. return net.IP(ip4)
  120. }
  121. if n.Load(&ip6) == nil {
  122. return net.IP(ip6)
  123. }
  124. return nil
  125. }
  126. // Quorum
  127. func (n *Node) Host() string {
  128. var hostname string
  129. n.Load((*enr.Hostname)(&hostname))
  130. return hostname
  131. }
  132. // End-Quorum
  133. // UDP returns the UDP port of the node.
  134. func (n *Node) UDP() int {
  135. var port enr.UDP
  136. n.Load(&port)
  137. return int(port)
  138. }
  139. // used by Quorum RAFT - returns the Raft port of the node
  140. func (n *Node) RaftPort() int {
  141. var port enr.RaftPort
  142. err := n.Load(&port)
  143. if err != nil {
  144. return 0
  145. }
  146. return int(port)
  147. }
  148. func (n *Node) HasRaftPort() bool {
  149. return n.RaftPort() > 0
  150. }
  151. // UDP returns the TCP port of the node.
  152. func (n *Node) TCP() int {
  153. var port enr.TCP
  154. n.Load(&port)
  155. return int(port)
  156. }
  157. // Pubkey returns the secp256k1 public key of the node, if present.
  158. func (n *Node) Pubkey() *ecdsa.PublicKey {
  159. var key ecdsa.PublicKey
  160. if n.Load((*Secp256k1)(&key)) != nil {
  161. return nil
  162. }
  163. return &key
  164. }
  165. // Record returns the node's record. The return value is a copy and may
  166. // be modified by the caller.
  167. func (n *Node) Record() *enr.Record {
  168. cpy := n.r
  169. return &cpy
  170. }
  171. // ValidateComplete checks whether n has a valid IP and UDP port.
  172. // Deprecated: don't use this method.
  173. func (n *Node) ValidateComplete() error {
  174. if n.Incomplete() {
  175. return errors.New("missing IP address")
  176. }
  177. if n.UDP() == 0 {
  178. return errors.New("missing UDP port")
  179. }
  180. ip := n.IP()
  181. if ip.IsMulticast() || ip.IsUnspecified() {
  182. return errors.New("invalid IP (multicast/unspecified)")
  183. }
  184. // Validate the node key (on curve, etc.).
  185. var key Secp256k1
  186. return n.Load(&key)
  187. }
  188. // String returns the text representation of the record.
  189. func (n *Node) String() string {
  190. if isNewV4(n) {
  191. return n.URLv4() // backwards-compatibility glue for NewV4 nodes
  192. }
  193. enc, _ := rlp.EncodeToBytes(&n.r) // always succeeds because record is valid
  194. b64 := base64.RawURLEncoding.EncodeToString(enc)
  195. return "enr:" + b64
  196. }
  197. // MarshalText implements encoding.TextMarshaler.
  198. func (n *Node) MarshalText() ([]byte, error) {
  199. return []byte(n.String()), nil
  200. }
  201. // UnmarshalText implements encoding.TextUnmarshaler.
  202. func (n *Node) UnmarshalText(text []byte) error {
  203. dec, err := Parse(ValidSchemes, string(text))
  204. if err == nil {
  205. *n = *dec
  206. }
  207. return err
  208. }
  209. // ID is a unique identifier for each node.
  210. type ID [32]byte
  211. // Bytes returns a byte slice representation of the ID
  212. func (n ID) Bytes() []byte {
  213. return n[:]
  214. }
  215. // ID prints as a long hexadecimal number.
  216. func (n ID) String() string {
  217. return fmt.Sprintf("%x", n[:])
  218. }
  219. // The Go syntax representation of a ID is a call to HexID.
  220. func (n ID) GoString() string {
  221. return fmt.Sprintf("enode.HexID(\"%x\")", n[:])
  222. }
  223. // TerminalString returns a shortened hex string for terminal logging.
  224. func (n ID) TerminalString() string {
  225. return hex.EncodeToString(n[:8])
  226. }
  227. // MarshalText implements the encoding.TextMarshaler interface.
  228. func (n ID) MarshalText() ([]byte, error) {
  229. return []byte(hex.EncodeToString(n[:])), nil
  230. }
  231. // UnmarshalText implements the encoding.TextUnmarshaler interface.
  232. func (n *ID) UnmarshalText(text []byte) error {
  233. id, err := ParseID(string(text))
  234. if err != nil {
  235. return err
  236. }
  237. *n = id
  238. return nil
  239. }
  240. // ID is a unique identifier for each node used by RAFT
  241. type EnodeID [64]byte
  242. // ID prints as a long hexadecimal number.
  243. func (n EnodeID) String() string {
  244. return fmt.Sprintf("%x", n[:])
  245. }
  246. // The Go syntax representation of a ID is a call to HexID.
  247. func (n EnodeID) GoString() string {
  248. return fmt.Sprintf("enode.HexID(\"%x\")", n[:])
  249. }
  250. // MarshalText implements the encoding.TextMarshaler interface.
  251. func (n EnodeID) MarshalText() ([]byte, error) {
  252. return []byte(hex.EncodeToString(n[:])), nil
  253. }
  254. // UnmarshalText implements the encoding.TextUnmarshaler interface.
  255. func (n *EnodeID) UnmarshalText(text []byte) error {
  256. id, err := RaftHexID(string(text))
  257. if err != nil {
  258. return err
  259. }
  260. *n = id
  261. return nil
  262. }
  263. // HexID converts a hex string to an ID.
  264. // The string may be prefixed with 0x.
  265. // It panics if the string is not a valid ID.
  266. func HexID(in string) ID {
  267. id, err := ParseID(in)
  268. if err != nil {
  269. panic(err)
  270. }
  271. return id
  272. }
  273. // used by Quorum RAFT to derive 64 byte nodeId from 128 byte enodeID
  274. func RaftHexID(in string) (EnodeID, error) {
  275. var id EnodeID
  276. b, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
  277. if err != nil {
  278. return id, err
  279. } else if len(b) != len(id) {
  280. return id, fmt.Errorf("wrong length, want %d hex chars", len(id)*2)
  281. }
  282. copy(id[:], b)
  283. return id, nil
  284. }
  285. func ParseID(in string) (ID, error) {
  286. var id ID
  287. b, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
  288. if err != nil {
  289. return id, err
  290. } else if len(b) != len(id) {
  291. return id, fmt.Errorf("wrong length, want %d hex chars", len(id)*2)
  292. }
  293. copy(id[:], b)
  294. return id, nil
  295. }
  296. // DistCmp compares the distances a->target and b->target.
  297. // Returns -1 if a is closer to target, 1 if b is closer to target
  298. // and 0 if they are equal.
  299. func DistCmp(target, a, b ID) int {
  300. for i := range target {
  301. da := a[i] ^ target[i]
  302. db := b[i] ^ target[i]
  303. if da > db {
  304. return 1
  305. } else if da < db {
  306. return -1
  307. }
  308. }
  309. return 0
  310. }
  311. // LogDist returns the logarithmic distance between a and b, log2(a ^ b).
  312. func LogDist(a, b ID) int {
  313. lz := 0
  314. for i := range a {
  315. x := a[i] ^ b[i]
  316. if x == 0 {
  317. lz += 8
  318. } else {
  319. lz += bits.LeadingZeros8(x)
  320. break
  321. }
  322. }
  323. return len(a)*8 - lz
  324. }