netgroup.h raw

   1  // Copyright (c) 2021-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_NETGROUP_H
   6  #define BITCOIN_NETGROUP_H
   7  
   8  #include <netaddress.h>
   9  #include <uint256.h>
  10  
  11  #include <cstddef>
  12  #include <vector>
  13  
  14  /**
  15   * Netgroup manager
  16   */
  17  class NetGroupManager {
  18  public:
  19      NetGroupManager(const NetGroupManager&) = delete;
  20      NetGroupManager(NetGroupManager&&) = default;
  21      NetGroupManager& operator=(const NetGroupManager&) = delete;
  22      NetGroupManager& operator=(NetGroupManager&&) = delete;
  23  
  24      static NetGroupManager WithEmbeddedAsmap(std::span<const std::byte> asmap) {
  25          return NetGroupManager(asmap, {});
  26      }
  27  
  28      static NetGroupManager WithLoadedAsmap(std::vector<std::byte>&& asmap) {
  29          return NetGroupManager(std::span{asmap}, std::move(asmap));
  30      }
  31  
  32      static NetGroupManager NoAsmap() {
  33          return NetGroupManager({}, {});
  34      }
  35  
  36      /** Get the asmap version, a checksum identifying the asmap being used. */
  37      uint256 GetAsmapVersion() const;
  38  
  39      /**
  40       * Get the canonical identifier of the network group for address.
  41       *
  42       * The groups are assigned in a way where it should be costly for an attacker to
  43       * obtain addresses with many different group identifiers, even if it is cheap
  44       * to obtain addresses with the same identifier.
  45       *
  46       * @note No two connections will be attempted to addresses with the same network
  47       *       group.
  48       */
  49      std::vector<unsigned char> GetGroup(const CNetAddr& address) const;
  50  
  51      /**
  52       *  Get the autonomous system on the BGP path to address.
  53       *
  54       *  The ip->AS mapping depends on how asmap is constructed.
  55       */
  56      uint32_t GetMappedAS(const CNetAddr& address) const;
  57  
  58      /**
  59       *  Analyze and log current health of ASMap based buckets.
  60       */
  61      void ASMapHealthCheck(const std::vector<CNetAddr>& clearnet_addrs) const;
  62  
  63      /**
  64       *  Indicates whether ASMap is being used for clearnet bucketing.
  65       */
  66      bool UsingASMap() const;
  67  
  68  private:
  69      /** Compressed IP->ASN mapping.
  70       *
  71       * Data may be loaded from a file when a node starts or embedded in the
  72       * binary.
  73       *
  74       * This mapping is then used for bucketing nodes in Addrman and for
  75       * ensuring we connect to a diverse set of peers in Connman. The map is
  76       * empty if no file was provided.
  77       *
  78       * If asmap is provided, nodes will be bucketed by AS they belong to, in
  79       * order to make impossible for a node to connect to several nodes hosted
  80       * in a single AS. This is done in response to Erebus attack, but also to
  81       * generally diversify the connections every node creates, especially
  82       * useful when a large fraction of nodes operate under a couple of cloud
  83       * providers.
  84       *
  85       * If a new asmap is provided, the existing addrman records are
  86       * re-bucketed.
  87       *
  88       * This is initialized in the constructor, const, and therefore is
  89       * thread-safe. m_asmap can either point to m_loaded_asmap which holds
  90       * data loaded from an external file at runtime or it can point to embedded
  91       * asmap data.
  92       */
  93      const std::span<const std::byte> m_asmap;
  94      std::vector<std::byte> m_loaded_asmap;
  95  
  96      explicit NetGroupManager(std::span<const std::byte> embedded_asmap, std::vector<std::byte>&& loaded_asmap)
  97          : m_asmap{embedded_asmap},
  98            m_loaded_asmap{std::move(loaded_asmap)}
  99      {
 100          assert(m_loaded_asmap.empty() || m_asmap.data() == m_loaded_asmap.data());
 101      }
 102  };
 103  
 104  #endif // BITCOIN_NETGROUP_H
 105