Bitcoin Core
31.1.0
P2P Digital Currency
Toggle main menu visibility
Loading...
Searching...
No Matches
src
netgroup.cpp
Go to the documentation of this file.
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
#include <
netgroup.h
>
6
7
#include <
hash.h
>
8
#include <
logging.h
>
9
#include <
uint256.h
>
10
#include <
util/asmap.h
>
11
12
#include <cstddef>
13
14
uint256
NetGroupManager::GetAsmapVersion
()
const
15
{
16
return
AsmapVersion
(
m_asmap
);
17
}
18
19
std::vector<unsigned char>
NetGroupManager::GetGroup
(
const
CNetAddr
& address)
const
20
{
21
std::vector<unsigned char> vchRet;
22
// If non-empty asmap is supplied and the address is IPv4/IPv6,
23
// return ASN to be used for bucketing.
24
uint32_t asn =
GetMappedAS
(address);
25
if
(asn != 0) {
// Either asmap was empty, or address has non-asmappable net class (e.g. TOR).
26
vchRet.push_back(
NET_IPV6
);
// IPv4 and IPv6 with same ASN should be in the same bucket
27
for
(
int
i = 0; i < 4; i++) {
28
vchRet.push_back((asn >> (8 * i)) & 0xFF);
29
}
30
return
vchRet;
31
}
32
33
vchRet.push_back(address.
GetNetClass
());
34
int
nStartByte{0};
35
int
nBits{0};
36
37
if
(address.
IsLocal
()) {
38
// all local addresses belong to the same group
39
}
else
if
(address.
IsInternal
()) {
40
// All internal-usage addresses get their own group.
41
// Skip over the INTERNAL_IN_IPV6_PREFIX returned by CAddress::GetAddrBytes().
42
nStartByte = INTERNAL_IN_IPV6_PREFIX.size();
43
nBits = ADDR_INTERNAL_SIZE * 8;
44
}
else
if
(!address.
IsRoutable
()) {
45
// all other unroutable addresses belong to the same group
46
}
else
if
(address.
HasLinkedIPv4
()) {
47
// IPv4 addresses (and mapped IPv4 addresses) use /16 groups
48
uint32_t ipv4 = address.
GetLinkedIPv4
();
49
vchRet.push_back((ipv4 >> 24) & 0xFF);
50
vchRet.push_back((ipv4 >> 16) & 0xFF);
51
return
vchRet;
52
}
else
if
(address.
IsTor
() || address.
IsI2P
()) {
53
nBits = 4;
54
}
else
if
(address.
IsCJDNS
()) {
55
// Treat in the same way as Tor and I2P because the address in all of
56
// them is "random" bytes (derived from a public key). However in CJDNS
57
// the first byte is a constant (see CJDNS_PREFIX), so the random bytes
58
// come after it. Thus skip the constant 8 bits at the start.
59
nBits = 12;
60
}
else
if
(address.
IsHeNet
()) {
61
// for he.net, use /36 groups
62
nBits = 36;
63
}
else
{
64
// for the rest of the IPv6 network, use /32 groups
65
nBits = 32;
66
}
67
68
// Push our address onto vchRet.
69
auto
addr_bytes = address.
GetAddrBytes
();
70
const
size_t
num_bytes = nBits / 8;
71
vchRet.insert(vchRet.end(), addr_bytes.begin() + nStartByte, addr_bytes.begin() + nStartByte + num_bytes);
72
nBits %= 8;
73
// ...for the last byte, push nBits and for the rest of the byte push 1's
74
if
(nBits > 0) {
75
assert
(num_bytes < addr_bytes.size());
76
vchRet.push_back(addr_bytes[num_bytes + nStartByte] | ((1 << (8 - nBits)) - 1));
77
}
78
79
return
vchRet;
80
}
81
82
uint32_t
NetGroupManager::GetMappedAS
(
const
CNetAddr
& address)
const
83
{
84
uint32_t net_class = address.
GetNetClass
();
85
if
(
m_asmap
.empty() || (net_class !=
NET_IPV4
&& net_class !=
NET_IPV6
)) {
86
return
0;
// Indicates not found, safe because AS0 is reserved per RFC7607.
87
}
88
std::vector<std::byte> ip_bytes(16);
89
if
(address.
HasLinkedIPv4
()) {
90
// For lookup, treat as if it was just an IPv4 address (IPV4_IN_IPV6_PREFIX + IPv4 bits)
91
std::copy_n(std::as_bytes(std::span{IPV4_IN_IPV6_PREFIX}).begin(),
92
IPV4_IN_IPV6_PREFIX.size(), ip_bytes.begin());
93
uint32_t ipv4 = address.
GetLinkedIPv4
();
94
for
(
int
i = 0; i < 4; ++i) {
95
ip_bytes[12 + i] = std::byte((ipv4 >> (24 - i * 8)) & 0xFF);
96
}
97
}
else
{
98
// Use all 128 bits of the IPv6 address otherwise
99
assert
(address.
IsIPv6
());
100
auto
addr_bytes = address.
GetAddrBytes
();
101
assert
(addr_bytes.size() == ip_bytes.size());
102
std::copy_n(std::as_bytes(std::span{addr_bytes}).begin(),
103
addr_bytes.size(), ip_bytes.begin());
104
}
105
uint32_t mapped_as =
Interpret
(
m_asmap
, ip_bytes);
106
return
mapped_as;
107
}
108
109
void
NetGroupManager::ASMapHealthCheck
(
const
std::vector<CNetAddr>& clearnet_addrs)
const
{
110
std::set<uint32_t> clearnet_asns{};
111
int
unmapped_count{0};
112
113
for
(
const
auto
& addr : clearnet_addrs) {
114
uint32_t asn =
GetMappedAS
(addr);
115
if
(asn == 0) {
116
++unmapped_count;
117
continue
;
118
}
119
clearnet_asns.insert(asn);
120
}
121
122
LogInfo
(
"ASMap Health Check: %i clearnet peers are mapped to %i ASNs with %i peers being unmapped\n"
, clearnet_addrs.size(), clearnet_asns.size(), unmapped_count);
123
}
124
125
bool
NetGroupManager::UsingASMap
()
const
{
126
return
m_asmap
.size() > 0;
127
}
asmap.h
CNetAddr
Network address.
Definition
netaddress.h:113
CNetAddr::GetNetClass
Network GetNetClass() const
Definition
netaddress.cpp:674
CNetAddr::GetAddrBytes
std::vector< unsigned char > GetAddrBytes() const
Definition
netaddress.cpp:692
CNetAddr::IsCJDNS
bool IsCJDNS() const
Definition
netaddress.h:177
CNetAddr::IsTor
bool IsTor() const
Definition
netaddress.h:175
CNetAddr::IsRoutable
bool IsRoutable() const
Definition
netaddress.cpp:462
CNetAddr::HasLinkedIPv4
bool HasLinkedIPv4() const
Whether this address has a linked IPv4 address (see GetLinkedIPv4()).
Definition
netaddress.cpp:652
CNetAddr::GetLinkedIPv4
uint32_t GetLinkedIPv4() const
For IPv4, mapped IPv4, SIIT translated IPv4, Teredo, 6to4 tunneled addresses, return the relevant IPv...
Definition
netaddress.cpp:657
CNetAddr::IsHeNet
bool IsHeNet() const
Definition
netaddress.cpp:393
CNetAddr::IsLocal
bool IsLocal() const
Definition
netaddress.cpp:398
CNetAddr::IsIPv6
bool IsIPv6() const
Definition
netaddress.h:159
CNetAddr::IsInternal
bool IsInternal() const
Definition
netaddress.cpp:472
CNetAddr::IsI2P
bool IsI2P() const
Definition
netaddress.h:176
NetGroupManager::GetAsmapVersion
uint256 GetAsmapVersion() const
Get the asmap version, a checksum identifying the asmap being used.
Definition
netgroup.cpp:14
NetGroupManager::UsingASMap
bool UsingASMap() const
Indicates whether ASMap is being used for clearnet bucketing.
Definition
netgroup.cpp:125
NetGroupManager::ASMapHealthCheck
void ASMapHealthCheck(const std::vector< CNetAddr > &clearnet_addrs) const
Analyze and log current health of ASMap based buckets.
Definition
netgroup.cpp:109
NetGroupManager::m_asmap
const std::span< const std::byte > m_asmap
Compressed IP->ASN mapping.
Definition
netgroup.h:93
NetGroupManager::GetGroup
std::vector< unsigned char > GetGroup(const CNetAddr &address) const
Get the canonical identifier of the network group for address.
Definition
netgroup.cpp:19
NetGroupManager::GetMappedAS
uint32_t GetMappedAS(const CNetAddr &address) const
Get the autonomous system on the BGP path to address.
Definition
netgroup.cpp:82
uint256
256-bit opaque blob.
Definition
uint256.h:195
hash.h
LogInfo
#define LogInfo(...)
Definition
log.h:95
logging.h
NET_IPV6
@ NET_IPV6
IPv6.
Definition
netaddress.h:41
NET_IPV4
@ NET_IPV4
IPv4.
Definition
netaddress.h:38
netgroup.h
uint256.h
Interpret
uint32_t Interpret(const std::span< const std::byte > asmap, const std::span< const std::byte > ip)
Execute the ASMap bytecode to find the ASN for an IP.
Definition
asmap.cpp:182
AsmapVersion
uint256 AsmapVersion(const std::span< const std::byte > data)
Computes SHA256 hash of ASMap data for versioning and consistency checks.
Definition
asmap.cpp:348
assert
assert(!tx.IsCoinBase())
Generated on
for Bitcoin Core by
1.18.0