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