netaddress.h raw

   1  // Copyright (c) 2009-present The Bitcoin Core developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   4  
   5  #ifndef BITCOIN_NETADDRESS_H
   6  #define BITCOIN_NETADDRESS_H
   7  
   8  #include <compat/compat.h>
   9  #include <crypto/siphash.h>
  10  #include <prevector.h>
  11  #include <random.h>
  12  #include <serialize.h>
  13  #include <tinyformat.h>
  14  #include <util/strencodings.h>
  15  #include <util/string.h>
  16  
  17  #include <array>
  18  #include <cstdint>
  19  #include <ios>
  20  #include <string>
  21  #include <string_view>
  22  #include <vector>
  23  
  24  /**
  25   * A network type.
  26   * @note An address may belong to more than one network, for example `10.0.0.1`
  27   * belongs to both `NET_UNROUTABLE` and `NET_IPV4`.
  28   * Keep these sequential starting from 0 and `NET_MAX` as the last entry.
  29   * We have loops like `for (int i = 0; i < NET_MAX; ++i)` that expect to iterate
  30   * over all enum values and also `GetExtNetwork()` "extends" this enum by
  31   * introducing standalone constants starting from `NET_MAX`.
  32   */
  33  enum Network {
  34      /// Addresses from these networks are not publicly routable on the global Internet.
  35      NET_UNROUTABLE = 0,
  36  
  37      /// IPv4
  38      NET_IPV4,
  39  
  40      /// IPv6
  41      NET_IPV6,
  42  
  43      /// TOR (v2 or v3)
  44      NET_ONION,
  45  
  46      /// I2P
  47      NET_I2P,
  48  
  49      /// CJDNS
  50      NET_CJDNS,
  51  
  52      /// A set of addresses that represent the hash of a string or FQDN. We use
  53      /// them in AddrMan to keep track of which DNS seeds were used.
  54      NET_INTERNAL,
  55  
  56      /// Dummy value to indicate the number of NET_* constants.
  57      NET_MAX,
  58  };
  59  
  60  /// Prefix of an IPv6 address when it contains an embedded IPv4 address.
  61  /// Used when (un)serializing addresses in ADDRv1 format (pre-BIP155).
  62  static const std::array<uint8_t, 12> IPV4_IN_IPV6_PREFIX{
  63      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF};
  64  
  65  /// Prefix of an IPv6 address when it contains an embedded TORv2 address.
  66  /// Used when (un)serializing addresses in ADDRv1 format (pre-BIP155).
  67  /// Such dummy IPv6 addresses are guaranteed to not be publicly routable as they
  68  /// fall under RFC4193's fc00::/7 subnet allocated to unique-local addresses.
  69  static const std::array<uint8_t, 6> TORV2_IN_IPV6_PREFIX{
  70      0xFD, 0x87, 0xD8, 0x7E, 0xEB, 0x43};
  71  
  72  /// Prefix of an IPv6 address when it contains an embedded "internal" address.
  73  /// Used when (un)serializing addresses in ADDRv1 format (pre-BIP155).
  74  /// The prefix comes from 0xFD + SHA256("bitcoin")[0:5].
  75  /// Such dummy IPv6 addresses are guaranteed to not be publicly routable as they
  76  /// fall under RFC4193's fc00::/7 subnet allocated to unique-local addresses.
  77  static const std::array<uint8_t, 6> INTERNAL_IN_IPV6_PREFIX{
  78      0xFD, 0x6B, 0x88, 0xC0, 0x87, 0x24 // 0xFD + sha256("bitcoin")[0:5].
  79  };
  80  
  81  /// All CJDNS addresses start with 0xFC. See
  82  /// https://github.com/cjdelisle/cjdns/blob/master/doc/Whitepaper.md#pulling-it-all-together
  83  static constexpr uint8_t CJDNS_PREFIX{0xFC};
  84  
  85  /// Size of IPv4 address (in bytes).
  86  static constexpr size_t ADDR_IPV4_SIZE = 4;
  87  
  88  /// Size of IPv6 address (in bytes).
  89  static constexpr size_t ADDR_IPV6_SIZE = 16;
  90  
  91  /// Size of TORv3 address (in bytes). This is the length of just the address
  92  /// as used in BIP155, without the checksum and the version byte.
  93  static constexpr size_t ADDR_TORV3_SIZE = 32;
  94  
  95  /// Size of I2P address (in bytes).
  96  static constexpr size_t ADDR_I2P_SIZE = 32;
  97  
  98  /// Size of CJDNS address (in bytes).
  99  static constexpr size_t ADDR_CJDNS_SIZE = 16;
 100  
 101  /// Size of "internal" (NET_INTERNAL) address (in bytes).
 102  static constexpr size_t ADDR_INTERNAL_SIZE = 10;
 103  
 104  /// SAM 3.1 and earlier do not support specifying ports and force the port to 0.
 105  static constexpr uint16_t I2P_SAM31_PORT{0};
 106  
 107  std::string OnionToString(std::span<const uint8_t> addr);
 108  
 109  /**
 110   * Network address.
 111   */
 112  class CNetAddr
 113  {
 114  protected:
 115      /**
 116       * Raw representation of the network address.
 117       * In network byte order (big endian) for IPv4 and IPv6.
 118       */
 119      prevector<ADDR_IPV6_SIZE, uint8_t> m_addr{ADDR_IPV6_SIZE, 0x0};
 120  
 121      /**
 122       * Network to which this address belongs.
 123       */
 124      Network m_net{NET_IPV6};
 125  
 126      /**
 127       * Scope id if scoped/link-local IPV6 address.
 128       * See https://tools.ietf.org/html/rfc4007
 129       */
 130      uint32_t m_scope_id{0};
 131  
 132  public:
 133      CNetAddr();
 134      explicit CNetAddr(const struct in_addr& ipv4Addr);
 135      void SetIP(const CNetAddr& ip);
 136  
 137      /**
 138       * Set from a legacy IPv6 address.
 139       * Legacy IPv6 address may be a normal IPv6 address, or another address
 140       * (e.g. IPv4) disguised as IPv6. This encoding is used in the legacy
 141       * `addr` encoding.
 142       */
 143      void SetLegacyIPv6(std::span<const uint8_t> ipv6);
 144  
 145      bool SetInternal(const std::string& name);
 146  
 147      /**
 148       * Parse a Tor or I2P address and set this object to it.
 149       * @param[in] addr Address to parse, for example
 150       * pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion or
 151       * ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p.
 152       * @returns Whether the operation was successful.
 153       * @see CNetAddr::IsTor(), CNetAddr::IsI2P()
 154       */
 155      bool SetSpecial(std::string_view addr);
 156  
 157      bool IsBindAny() const; // INADDR_ANY equivalent
 158      [[nodiscard]] bool IsIPv4() const { return m_net == NET_IPV4; } // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
 159      [[nodiscard]] bool IsIPv6() const { return m_net == NET_IPV6; } // IPv6 address (not mapped IPv4, not Tor)
 160      bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
 161      bool IsRFC2544() const; // IPv4 inter-network communications (198.18.0.0/15)
 162      bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10)
 163      bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24)
 164      bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
 165      bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
 166      bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16)
 167      bool IsRFC4193() const; // IPv6 unique local (FC00::/7)
 168      bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32)
 169      bool IsRFC4843() const; // IPv6 ORCHID (deprecated) (2001:10::/28)
 170      bool IsRFC7343() const; // IPv6 ORCHIDv2 (2001:20::/28)
 171      bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
 172      bool IsRFC6052() const; // IPv6 well-known prefix for IPv4-embedded address (64:FF9B::/96)
 173      bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) (actually defined in RFC2765)
 174      bool IsHeNet() const;   // IPv6 Hurricane Electric - https://he.net (2001:0470::/36)
 175      [[nodiscard]] bool IsTor() const { return m_net == NET_ONION; }
 176      [[nodiscard]] bool IsI2P() const { return m_net == NET_I2P; }
 177      [[nodiscard]] bool IsCJDNS() const { return m_net == NET_CJDNS; }
 178      [[nodiscard]] bool HasCJDNSPrefix() const { return m_addr[0] == CJDNS_PREFIX; }
 179      bool IsLocal() const;
 180      bool IsRoutable() const;
 181      bool IsInternal() const;
 182      bool IsValid() const;
 183  
 184      /**
 185       * Whether this object is a privacy network.
 186       * TODO: consider adding IsCJDNS() here when more peers adopt CJDNS, see:
 187       * https://github.com/bitcoin/bitcoin/pull/27411#issuecomment-1497176155
 188       */
 189      [[nodiscard]] bool IsPrivacyNet() const { return IsTor() || IsI2P(); }
 190  
 191      /**
 192       * Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
 193       */
 194      bool IsAddrV1Compatible() const;
 195  
 196      enum Network GetNetwork() const;
 197      std::string ToStringAddr() const;
 198      bool GetInAddr(struct in_addr* pipv4Addr) const;
 199      Network GetNetClass() const;
 200  
 201      //! For IPv4, mapped IPv4, SIIT translated IPv4, Teredo, 6to4 tunneled addresses, return the relevant IPv4 address as a uint32.
 202      uint32_t GetLinkedIPv4() const;
 203      //! Whether this address has a linked IPv4 address (see GetLinkedIPv4()).
 204      bool HasLinkedIPv4() const;
 205  
 206      std::vector<unsigned char> GetAddrBytes() const;
 207      int GetReachabilityFrom(const CNetAddr& paddrPartner) const;
 208  
 209      explicit CNetAddr(const struct in6_addr& pipv6Addr, uint32_t scope = 0);
 210      bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
 211  
 212      friend bool operator==(const CNetAddr& a, const CNetAddr& b);
 213      friend bool operator<(const CNetAddr& a, const CNetAddr& b);
 214  
 215      /**
 216       * Whether this address should be relayed to other peers even if we can't reach it ourselves.
 217       */
 218      bool IsRelayable() const
 219      {
 220          return IsIPv4() || IsIPv6() || IsTor() || IsI2P() || IsCJDNS();
 221      }
 222  
 223      enum class Encoding {
 224          V1,
 225          V2, //!< BIP155 encoding
 226      };
 227      struct SerParams {
 228          const Encoding enc;
 229          SER_PARAMS_OPFUNC
 230      };
 231      static constexpr SerParams V1{Encoding::V1};
 232      static constexpr SerParams V2{Encoding::V2};
 233  
 234      /**
 235       * Serialize to a stream.
 236       */
 237      template <typename Stream>
 238      void Serialize(Stream& s) const
 239      {
 240          if (s.template GetParams<SerParams>().enc == Encoding::V2) {
 241              SerializeV2Stream(s);
 242          } else {
 243              SerializeV1Stream(s);
 244          }
 245      }
 246  
 247      /**
 248       * Unserialize from a stream.
 249       */
 250      template <typename Stream>
 251      void Unserialize(Stream& s)
 252      {
 253          if (s.template GetParams<SerParams>().enc == Encoding::V2) {
 254              UnserializeV2Stream(s);
 255          } else {
 256              UnserializeV1Stream(s);
 257          }
 258      }
 259  
 260      /**
 261       * BIP155 network ids recognized by this software.
 262       */
 263      enum BIP155Network : uint8_t {
 264          IPV4 = 1,
 265          IPV6 = 2,
 266          TORV2 = 3,
 267          TORV3 = 4,
 268          I2P = 5,
 269          CJDNS = 6,
 270      };
 271  
 272      friend class CSubNet;
 273  
 274  private:
 275      /**
 276       * Parse a Tor address and set this object to it.
 277       * @param[in] addr Address to parse, must be a valid C string, for example
 278       * pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion.
 279       * @returns Whether the operation was successful.
 280       * @see CNetAddr::IsTor()
 281       */
 282      bool SetTor(std::string_view addr);
 283  
 284      /**
 285       * Parse an I2P address and set this object to it.
 286       * @param[in] addr Address to parse, must be a valid C string, for example
 287       * ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p.
 288       * @returns Whether the operation was successful.
 289       * @see CNetAddr::IsI2P()
 290       */
 291      bool SetI2P(std::string_view addr);
 292  
 293      /**
 294       * Size of CNetAddr when serialized as ADDRv1 (pre-BIP155) (in bytes).
 295       */
 296      static constexpr size_t V1_SERIALIZATION_SIZE = ADDR_IPV6_SIZE;
 297  
 298      /**
 299       * Maximum size of an address as defined in BIP155 (in bytes).
 300       * This is only the size of the address, not the entire CNetAddr object
 301       * when serialized.
 302       */
 303      static constexpr size_t MAX_ADDRV2_SIZE = 512;
 304  
 305      /**
 306       * Get the BIP155 network id of this address.
 307       * Must not be called for IsInternal() objects.
 308       * @returns BIP155 network id, except TORV2 which is no longer supported.
 309       */
 310      BIP155Network GetBIP155Network() const;
 311  
 312      /**
 313       * Set `m_net` from the provided BIP155 network id and size after validation.
 314       * @retval true the network was recognized, is valid and `m_net` was set
 315       * @retval false not recognised (from future?) and should be silently ignored
 316       * @throws std::ios_base::failure if the network is one of the BIP155 founding
 317       * networks (id 1..6) with wrong address size.
 318       */
 319      bool SetNetFromBIP155Network(uint8_t possible_bip155_net, size_t address_size);
 320  
 321      /**
 322       * Serialize in pre-ADDRv2/BIP155 format to an array.
 323       */
 324      void SerializeV1Array(uint8_t (&arr)[V1_SERIALIZATION_SIZE]) const
 325      {
 326          size_t prefix_size;
 327  
 328          switch (m_net) {
 329          case NET_IPV6:
 330              assert(m_addr.size() == sizeof(arr));
 331              memcpy(arr, m_addr.data(), m_addr.size());
 332              return;
 333          case NET_IPV4:
 334              prefix_size = sizeof(IPV4_IN_IPV6_PREFIX);
 335              assert(prefix_size + m_addr.size() == sizeof(arr));
 336              memcpy(arr, IPV4_IN_IPV6_PREFIX.data(), prefix_size);
 337              memcpy(arr + prefix_size, m_addr.data(), m_addr.size());
 338              return;
 339          case NET_INTERNAL:
 340              prefix_size = sizeof(INTERNAL_IN_IPV6_PREFIX);
 341              assert(prefix_size + m_addr.size() == sizeof(arr));
 342              memcpy(arr, INTERNAL_IN_IPV6_PREFIX.data(), prefix_size);
 343              memcpy(arr + prefix_size, m_addr.data(), m_addr.size());
 344              return;
 345          case NET_ONION:
 346          case NET_I2P:
 347          case NET_CJDNS:
 348              break;
 349          case NET_UNROUTABLE:
 350          case NET_MAX:
 351              assert(false);
 352          } // no default case, so the compiler can warn about missing cases
 353  
 354          // Serialize ONION, I2P and CJDNS as all-zeros.
 355          memset(arr, 0x0, V1_SERIALIZATION_SIZE);
 356      }
 357  
 358      /**
 359       * Serialize in pre-ADDRv2/BIP155 format to a stream.
 360       */
 361      template <typename Stream>
 362      void SerializeV1Stream(Stream& s) const
 363      {
 364          uint8_t serialized[V1_SERIALIZATION_SIZE];
 365  
 366          SerializeV1Array(serialized);
 367  
 368          s << serialized;
 369      }
 370  
 371      /**
 372       * Serialize as ADDRv2 / BIP155.
 373       */
 374      template <typename Stream>
 375      void SerializeV2Stream(Stream& s) const
 376      {
 377          if (IsInternal()) {
 378              // Serialize NET_INTERNAL as embedded in IPv6. We need to
 379              // serialize such addresses from addrman.
 380              s << static_cast<uint8_t>(BIP155Network::IPV6);
 381              s << COMPACTSIZE(ADDR_IPV6_SIZE);
 382              SerializeV1Stream(s);
 383              return;
 384          }
 385  
 386          s << static_cast<uint8_t>(GetBIP155Network());
 387          s << m_addr;
 388      }
 389  
 390      /**
 391       * Unserialize from a pre-ADDRv2/BIP155 format from an array.
 392       *
 393       * This function is only called from UnserializeV1Stream() and is a wrapper
 394       * for SetLegacyIPv6(); however, we keep it for symmetry with
 395       * SerializeV1Array() to have pairs of ser/unser functions and to make clear
 396       * that if one is altered, a corresponding reverse modification should be
 397       * applied to the other.
 398       */
 399      void UnserializeV1Array(uint8_t (&arr)[V1_SERIALIZATION_SIZE])
 400      {
 401          // Use SetLegacyIPv6() so that m_net is set correctly. For example
 402          // ::FFFF:0102:0304 should be set as m_net=NET_IPV4 (1.2.3.4).
 403          SetLegacyIPv6(arr);
 404      }
 405  
 406      /**
 407       * Unserialize from a pre-ADDRv2/BIP155 format from a stream.
 408       */
 409      template <typename Stream>
 410      void UnserializeV1Stream(Stream& s)
 411      {
 412          uint8_t serialized[V1_SERIALIZATION_SIZE];
 413  
 414          s >> serialized;
 415  
 416          UnserializeV1Array(serialized);
 417      }
 418  
 419      /**
 420       * Unserialize from a ADDRv2 / BIP155 format.
 421       */
 422      template <typename Stream>
 423      void UnserializeV2Stream(Stream& s)
 424      {
 425          uint8_t bip155_net;
 426          s >> bip155_net;
 427  
 428          size_t address_size;
 429          s >> COMPACTSIZE(address_size);
 430  
 431          if (address_size > MAX_ADDRV2_SIZE) {
 432              throw std::ios_base::failure(strprintf(
 433                  "Address too long: %u > %u", address_size, MAX_ADDRV2_SIZE));
 434          }
 435  
 436          m_scope_id = 0;
 437  
 438          if (SetNetFromBIP155Network(bip155_net, address_size)) {
 439              m_addr.resize(address_size);
 440              s >> std::span{m_addr};
 441  
 442              if (m_net != NET_IPV6) {
 443                  return;
 444              }
 445  
 446              // Do some special checks on IPv6 addresses.
 447  
 448              // Recognize NET_INTERNAL embedded in IPv6, such addresses are not
 449              // gossiped but could be coming from addrman, when unserializing from
 450              // disk.
 451              if (util::HasPrefix(m_addr, INTERNAL_IN_IPV6_PREFIX)) {
 452                  m_net = NET_INTERNAL;
 453                  memmove(m_addr.data(), m_addr.data() + INTERNAL_IN_IPV6_PREFIX.size(),
 454                          ADDR_INTERNAL_SIZE);
 455                  m_addr.resize(ADDR_INTERNAL_SIZE);
 456                  return;
 457              }
 458  
 459              if (!util::HasPrefix(m_addr, IPV4_IN_IPV6_PREFIX) &&
 460                  !util::HasPrefix(m_addr, TORV2_IN_IPV6_PREFIX)) {
 461                  return;
 462              }
 463  
 464              // IPv4 and TORv2 are not supposed to be embedded in IPv6 (like in V1
 465              // encoding). Unserialize as !IsValid(), thus ignoring them.
 466          } else {
 467              // If we receive an unknown BIP155 network id (from the future?) then
 468              // ignore the address - unserialize as !IsValid().
 469              s.ignore(address_size);
 470          }
 471  
 472          // Mimic a default-constructed CNetAddr object which is !IsValid() and thus
 473          // will not be gossiped, but continue reading next addresses from the stream.
 474          m_net = NET_IPV6;
 475          m_addr.assign(ADDR_IPV6_SIZE, 0x0);
 476      }
 477  };
 478  
 479  class CSubNet
 480  {
 481  protected:
 482      /// Network (base) address
 483      CNetAddr network;
 484      /// Netmask, in network byte order
 485      uint8_t netmask[16];
 486      /// Is this value valid? (only used to signal parse errors)
 487      bool valid;
 488  
 489  public:
 490      /**
 491       * Construct an invalid subnet (empty, `Match()` always returns false).
 492       */
 493      CSubNet();
 494  
 495      /**
 496       * Construct from a given network start and number of bits (CIDR mask).
 497       * @param[in] addr Network start. Must be IPv4 or IPv6, otherwise an invalid subnet is
 498       * created.
 499       * @param[in] mask CIDR mask, must be in [0, 32] for IPv4 addresses and in [0, 128] for
 500       * IPv6 addresses. Otherwise an invalid subnet is created.
 501       */
 502      CSubNet(const CNetAddr& addr, uint8_t mask);
 503  
 504      /**
 505       * Construct from a given network start and mask.
 506       * @param[in] addr Network start. Must be IPv4 or IPv6, otherwise an invalid subnet is
 507       * created.
 508       * @param[in] mask Network mask, must be of the same type as `addr` and not contain 0-bits
 509       * followed by 1-bits. Otherwise an invalid subnet is created.
 510       */
 511      CSubNet(const CNetAddr& addr, const CNetAddr& mask);
 512  
 513      /**
 514       * Construct a single-host subnet.
 515       * @param[in] addr The sole address to be contained in the subnet, can also be non-IPv[46].
 516       */
 517      explicit CSubNet(const CNetAddr& addr);
 518  
 519      bool Match(const CNetAddr& addr) const;
 520  
 521      std::string ToString() const;
 522      bool IsValid() const;
 523  
 524      friend bool operator==(const CSubNet& a, const CSubNet& b);
 525      friend bool operator<(const CSubNet& a, const CSubNet& b);
 526  };
 527  
 528  /** A combination of a network address (CNetAddr) and a (TCP) port */
 529  class CService : public CNetAddr
 530  {
 531  protected:
 532      uint16_t port; // host order
 533  
 534  public:
 535      CService();
 536      CService(const CNetAddr& ip, uint16_t port);
 537      CService(const struct in_addr& ipv4Addr, uint16_t port);
 538      explicit CService(const struct sockaddr_in& addr);
 539      uint16_t GetPort() const;
 540      bool GetSockAddr(struct sockaddr* paddr, socklen_t* addrlen) const;
 541      /**
 542       * Set CService from a network sockaddr.
 543       * @param[in] paddr Pointer to sockaddr structure
 544       * @param[in] addrlen Length of sockaddr structure in bytes. This will be checked to exactly match the length of
 545       * a socket address of the provided family, unless std::nullopt is passed
 546       * @returns true on success
 547       */
 548      bool SetSockAddr(const struct sockaddr* paddr, socklen_t addrlen);
 549      /**
 550       * Get the address family
 551       * @returns AF_UNSPEC if unspecified
 552       */
 553      [[nodiscard]] sa_family_t GetSAFamily() const;
 554      friend bool operator==(const CService& a, const CService& b);
 555      friend bool operator<(const CService& a, const CService& b);
 556      std::vector<unsigned char> GetKey() const;
 557      std::string ToStringAddrPort() const;
 558  
 559      CService(const struct in6_addr& ipv6Addr, uint16_t port);
 560      explicit CService(const struct sockaddr_in6& addr);
 561  
 562      SERIALIZE_METHODS(CService, obj)
 563      {
 564          READWRITE(AsBase<CNetAddr>(obj), Using<BigEndianFormatter<2>>(obj.port));
 565      }
 566  
 567      friend class CServiceHash;
 568      friend CService MaybeFlipIPv6toCJDNS(const CService& service);
 569  };
 570  
 571  class CServiceHash
 572  {
 573  public:
 574      CServiceHash()
 575          : m_salt_k0{FastRandomContext().rand64()},
 576            m_salt_k1{FastRandomContext().rand64()}
 577      {
 578      }
 579  
 580      CServiceHash(uint64_t salt_k0, uint64_t salt_k1) : m_salt_k0{salt_k0}, m_salt_k1{salt_k1} {}
 581  
 582      size_t operator()(const CService& a) const noexcept
 583      {
 584          CSipHasher hasher(m_salt_k0, m_salt_k1);
 585          hasher.Write(a.m_net);
 586          hasher.Write(a.port);
 587          hasher.Write(a.m_addr);
 588          return static_cast<size_t>(hasher.Finalize());
 589      }
 590  
 591  private:
 592      const uint64_t m_salt_k0;
 593      const uint64_t m_salt_k1;
 594  };
 595  
 596  #endif // BITCOIN_NETADDRESS_H
 597