node.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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. "blockchain-go/p2p/enr"
  27. "blockchain-go/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. // Incomplete returns true for nodes with no IP address.
  82. func (n *Node) Incomplete() bool {
  83. return n.IP() == nil
  84. }
  85. // Load retrieves an entry from the underlying record.
  86. func (n *Node) Load(k enr.Entry) error {
  87. return n.r.Load(k)
  88. }
  89. // IP returns the IP address of the node. This prefers IPv4 addresses.
  90. func (n *Node) IP() net.IP {
  91. var (
  92. ip4 enr.IPv4
  93. ip6 enr.IPv6
  94. )
  95. if n.Load(&ip4) == nil {
  96. return net.IP(ip4)
  97. }
  98. if n.Load(&ip6) == nil {
  99. return net.IP(ip6)
  100. }
  101. return nil
  102. }
  103. // UDP returns the UDP port of the node.
  104. func (n *Node) UDP() int {
  105. var port enr.UDP
  106. n.Load(&port)
  107. return int(port)
  108. }
  109. // UDP returns the TCP port of the node.
  110. func (n *Node) TCP() int {
  111. var port enr.TCP
  112. n.Load(&port)
  113. return int(port)
  114. }
  115. // Pubkey returns the secp256k1 public key of the node, if present.
  116. func (n *Node) Pubkey() *ecdsa.PublicKey {
  117. var key ecdsa.PublicKey
  118. if n.Load((*Secp256k1)(&key)) != nil {
  119. return nil
  120. }
  121. return &key
  122. }
  123. // Record returns the node's record. The return value is a copy and may
  124. // be modified by the caller.
  125. func (n *Node) Record() *enr.Record {
  126. cpy := n.r
  127. return &cpy
  128. }
  129. // ValidateComplete checks whether n has a valid IP and UDP port.
  130. // Deprecated: don't use this method.
  131. func (n *Node) ValidateComplete() error {
  132. if n.Incomplete() {
  133. return errors.New("missing IP address")
  134. }
  135. if n.UDP() == 0 {
  136. return errors.New("missing UDP port")
  137. }
  138. ip := n.IP()
  139. if ip.IsMulticast() || ip.IsUnspecified() {
  140. return errors.New("invalid IP (multicast/unspecified)")
  141. }
  142. // Validate the node key (on curve, etc.).
  143. var key Secp256k1
  144. return n.Load(&key)
  145. }
  146. // String returns the text representation of the record.
  147. func (n *Node) String() string {
  148. if isNewV4(n) {
  149. return n.URLv4() // backwards-compatibility glue for NewV4 nodes
  150. }
  151. enc, _ := rlp.EncodeToBytes(&n.r) // always succeeds because record is valid
  152. b64 := base64.RawURLEncoding.EncodeToString(enc)
  153. return "enr:" + b64
  154. }
  155. // MarshalText implements encoding.TextMarshaler.
  156. func (n *Node) MarshalText() ([]byte, error) {
  157. return []byte(n.String()), nil
  158. }
  159. // UnmarshalText implements encoding.TextUnmarshaler.
  160. func (n *Node) UnmarshalText(text []byte) error {
  161. dec, err := Parse(ValidSchemes, string(text))
  162. if err == nil {
  163. *n = *dec
  164. }
  165. return err
  166. }
  167. // ID is a unique identifier for each node.
  168. type ID [32]byte
  169. // Bytes returns a byte slice representation of the ID
  170. func (n ID) Bytes() []byte {
  171. return n[:]
  172. }
  173. // ID prints as a long hexadecimal number.
  174. func (n ID) String() string {
  175. return fmt.Sprintf("%x", n[:])
  176. }
  177. // The Go syntax representation of a ID is a call to HexID.
  178. func (n ID) GoString() string {
  179. return fmt.Sprintf("enode.HexID(\"%x\")", n[:])
  180. }
  181. // TerminalString returns a shortened hex string for terminal logging.
  182. func (n ID) TerminalString() string {
  183. return hex.EncodeToString(n[:8])
  184. }
  185. // MarshalText implements the encoding.TextMarshaler interface.
  186. func (n ID) MarshalText() ([]byte, error) {
  187. return []byte(hex.EncodeToString(n[:])), nil
  188. }
  189. // UnmarshalText implements the encoding.TextUnmarshaler interface.
  190. func (n *ID) UnmarshalText(text []byte) error {
  191. id, err := ParseID(string(text))
  192. if err != nil {
  193. return err
  194. }
  195. *n = id
  196. return nil
  197. }
  198. // HexID converts a hex string to an ID.
  199. // The string may be prefixed with 0x.
  200. // It panics if the string is not a valid ID.
  201. func HexID(in string) ID {
  202. id, err := ParseID(in)
  203. if err != nil {
  204. panic(err)
  205. }
  206. return id
  207. }
  208. func ParseID(in string) (ID, error) {
  209. var id ID
  210. b, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
  211. if err != nil {
  212. return id, err
  213. } else if len(b) != len(id) {
  214. return id, fmt.Errorf("wrong length, want %d hex chars", len(id)*2)
  215. }
  216. copy(id[:], b)
  217. return id, nil
  218. }
  219. // DistCmp compares the distances a->target and b->target.
  220. // Returns -1 if a is closer to target, 1 if b is closer to target
  221. // and 0 if they are equal.
  222. func DistCmp(target, a, b ID) int {
  223. for i := range target {
  224. da := a[i] ^ target[i]
  225. db := b[i] ^ target[i]
  226. if da > db {
  227. return 1
  228. } else if da < db {
  229. return -1
  230. }
  231. }
  232. return 0
  233. }
  234. // LogDist returns the logarithmic distance between a and b, log2(a ^ b).
  235. func LogDist(a, b ID) int {
  236. lz := 0
  237. for i := range a {
  238. x := a[i] ^ b[i]
  239. if x == 0 {
  240. lz += 8
  241. } else {
  242. lz += bits.LeadingZeros8(x)
  243. break
  244. }
  245. }
  246. return len(a)*8 - lz
  247. }