v31.1-roots.1 · Commit 5: [PATCH 05/17] feat(net): preserve Roots peer controls and health view on v31
src/net.cpp
Before: src/net.cpp · After: src/net.cpp
File metadata
index 5c28efade891a8e412d358280e815fad2e367935..930fdc93475c267ab4f93f6839376dcddcec0226 100644
Download original patch · Release notes
Diff rows 1–137 of 137. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. Before is on the left; after is on the right. Unified view fits narrow screens more easily.
src/net.cpp
CHANGED
|
@@ -320,7 +320,7 @@ bool SeenLocal(const CService& addr)
|
|
| 320 |
LOCK(g_maplocalhost_mutex);
|
| 321 |
const auto it = mapLocalHost.find(addr);
|
| 322 |
if (it == mapLocalHost.end()) return false;
|
| 323 |
-
++it->second.nScore;
|
| 324 |
return true;
|
| 325 |
}
|
| 326 |
|
|
@@ -440,6 +440,10 @@ CNode* CConnman::ConnectNode(CAddress addrConnect,
|
|
| 440 |
std::unique_ptr<i2p::sam::Session> i2p_transient_session;
|
| 441 |
|
| 442 |
for (auto& target_addr: connect_to) {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 443 |
if (target_addr.IsValid()) {
|
| 444 |
bool use_proxy;
|
| 445 |
if (proxy_override.has_value()) {
|
|
@@ -511,8 +515,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect,
|
|
| 511 |
}
|
| 512 |
|
| 513 |
NetPermissionFlags permission_flags = NetPermissionFlags::None;
|
| 514 |
-
std::vector<NetWhitelistPermissions> whitelist_permissions = conn_type == ConnectionType::MANUAL ? vWhitelistedRangeOutgoing : std::vector<NetWhitelistPermissions>{};
|
| 515 |
-
AddWhitelistPermissionFlags(permission_flags, target_addr, whitelist_permissions);
|
| 516 |
|
| 517 |
// Add node
|
| 518 |
NodeId id = GetNewNodeId();
|
|
@@ -585,6 +588,7 @@ void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, std::optio
|
|
| 585 |
if (whitelist_relay) NetPermissions::AddFlag(flags, NetPermissionFlags::Relay);
|
| 586 |
NetPermissions::AddFlag(flags, NetPermissionFlags::Mempool);
|
| 587 |
NetPermissions::AddFlag(flags, NetPermissionFlags::NoBan);
|
|
|
|
| 588 |
}
|
| 589 |
}
|
| 590 |
|
|
@@ -658,6 +662,8 @@ void CNode::CopyStats(CNodeStats& stats)
|
|
| 658 |
stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToStringAddrPort() : "";
|
| 659 |
|
| 660 |
X(m_conn_type);
|
|
|
|
|
|
|
| 661 |
}
|
| 662 |
#undef X
|
| 663 |
|
|
@@ -1685,7 +1691,7 @@ std::pair<size_t, bool> CConnman::SocketSendData(CNode& node) const
|
|
| 1685 |
* to forge. In order to partition a node the attacker must be
|
| 1686 |
* simultaneously better at all of them than honest peers.
|
| 1687 |
*/
|
| 1688 |
-
bool CConnman::AttemptToEvictConnection()
|
| 1689 |
{
|
| 1690 |
std::vector<NodeEvictionCandidate> vEvictionCandidates;
|
| 1691 |
{
|
|
@@ -1713,7 +1719,7 @@ bool CConnman::AttemptToEvictConnection()
|
|
| 1713 |
vEvictionCandidates.push_back(candidate);
|
| 1714 |
}
|
| 1715 |
}
|
| 1716 |
-
const std::optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates));
|
| 1717 |
if (!node_id_to_evict) {
|
| 1718 |
return false;
|
| 1719 |
}
|
|
@@ -1769,7 +1775,14 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
|
|
| 1769 |
{
|
| 1770 |
int nInbound = 0;
|
| 1771 |
|
| 1772 |
-
const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1773 |
|
| 1774 |
// Tor inbound connections do not reveal the peer's actual network address.
|
| 1775 |
// Therefore do not apply address-based whitelist permissions to them.
|
|
@@ -1816,13 +1829,15 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
|
|
| 1816 |
return;
|
| 1817 |
}
|
| 1818 |
|
|
|
|
| 1819 |
if (nInbound >= m_max_inbound)
|
| 1820 |
{
|
| 1821 |
-
if (!AttemptToEvictConnection()) {
|
| 1822 |
// No connection to evict, disconnect the new connection
|
| 1823 |
LogDebug(BCLog::NET, "failed to find an eviction candidate - connection dropped (full)\n");
|
| 1824 |
return;
|
| 1825 |
}
|
|
|
|
| 1826 |
}
|
| 1827 |
|
| 1828 |
NodeId id = GetNewNodeId();
|
|
@@ -1851,6 +1866,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
|
|
| 1851 |
CNodeOptions{
|
| 1852 |
.permission_flags = permission_flags,
|
| 1853 |
.prefer_evict = discouraged,
|
|
|
|
| 1854 |
.recv_flood_size = nReceiveFloodSize,
|
| 1855 |
.use_v2transport = use_v2transport,
|
| 1856 |
});
|
|
@@ -1951,7 +1967,7 @@ void CConnman::DisconnectNodes()
|
|
| 1951 |
// Add to reconnection list if appropriate. We don't reconnect right here, because
|
| 1952 |
// the creation of a connection is a blocking operation (up to several seconds),
|
| 1953 |
// and we don't want to hold up the socket handler thread for that long.
|
| 1954 |
-
if (network_active && pnode->m_transport->ShouldReconnectV1()) {
|
| 1955 |
reconnections_to_add.push_back({
|
| 1956 |
.proxy_override = pnode->m_proxy_override,
|
| 1957 |
.addr_connect = pnode->addr,
|
|
@@ -3172,6 +3188,8 @@ void CConnman::ThreadMessageHandler()
|
|
| 3172 |
if (pnode->fDisconnect)
|
| 3173 |
continue;
|
| 3174 |
|
|
|
|
|
|
|
| 3175 |
// Receive messages
|
| 3176 |
bool fMoreNodeWork{m_msgproc->ProcessMessages(*pnode, flagInterruptMsgProc)};
|
| 3177 |
fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
|
|
@@ -3764,12 +3782,14 @@ std::vector<CAddress> CConnman::GetAddresses(CNode& requestor, size_t max_addres
|
|
| 3764 |
|
| 3765 |
bool CConnman::AddNode(const AddedNodeParams& add)
|
| 3766 |
{
|
| 3767 |
-
const CService resolved(LookupNumeric(add.m_added_node, GetDefaultPort(add.m_added_node)));
|
| 3768 |
-
const bool resolved_is_valid{resolved.IsValid()};
|
| 3769 |
-
|
| 3770 |
LOCK(m_added_nodes_mutex);
|
| 3771 |
for (const auto& it : m_added_node_params) {
|
| 3772 |
-
if (add.m_added_node == it.m_added_node || (resolved_is_valid && resolved == LookupNumeric(it.m_added_node, GetDefaultPort(it.m_added_node)))) return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3773 |
}
|
| 3774 |
|
| 3775 |
m_added_node_params.push_back(add);
|
|
@@ -4019,6 +4039,7 @@ CNode::CNode(NodeId idIn,
|
|
| 4019 |
m_addr_name{addrNameIn.empty() ? addr.ToStringAddrPort() : addrNameIn},
|
| 4020 |
m_dest(addrNameIn),
|
| 4021 |
m_inbound_onion{inbound_onion},
|
|
|
|
| 4022 |
m_prefer_evict{node_opts.prefer_evict},
|
| 4023 |
nKeyedNetGroup{nKeyedNetGroupIn},
|
| 4024 |
m_network_key{network_key},
|
|
|
|
| 320 |
LOCK(g_maplocalhost_mutex);
|
| 321 |
const auto it = mapLocalHost.find(addr);
|
| 322 |
if (it == mapLocalHost.end()) return false;
|
| 323 |
+
if (it->second.nScore < std::numeric_limits<int>::max()) ++it->second.nScore;
|
| 324 |
return true;
|
| 325 |
}
|
| 326 |
|
|
|
|
| 440 |
std::unique_ptr<i2p::sam::Session> i2p_transient_session;
|
| 441 |
|
| 442 |
for (auto& target_addr: connect_to) {
|
| 443 |
+
if (!use_v2transport && DisableV1OnClearnet(target_addr.GetNetClass())) {
|
| 444 |
+
LogDebug(BCLog::NET, "outbound v1 disabled on clearnet\n");
|
| 445 |
+
continue;
|
| 446 |
+
}
|
| 447 |
if (target_addr.IsValid()) {
|
| 448 |
bool use_proxy;
|
| 449 |
if (proxy_override.has_value()) {
|
|
|
|
| 515 |
}
|
| 516 |
|
| 517 |
NetPermissionFlags permission_flags = NetPermissionFlags::None;
|
| 518 |
+
AddWhitelistPermissionFlags(permission_flags, target_addr, vWhitelistedRangeOutgoing);
|
|
|
|
| 519 |
|
| 520 |
// Add node
|
| 521 |
NodeId id = GetNewNodeId();
|
|
|
|
| 588 |
if (whitelist_relay) NetPermissions::AddFlag(flags, NetPermissionFlags::Relay);
|
| 589 |
NetPermissions::AddFlag(flags, NetPermissionFlags::Mempool);
|
| 590 |
NetPermissions::AddFlag(flags, NetPermissionFlags::NoBan);
|
| 591 |
+
NetPermissions::AddFlag(flags, NetPermissionFlags::Addr);
|
| 592 |
}
|
| 593 |
}
|
| 594 |
|
|
|
|
| 662 |
stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToStringAddrPort() : "";
|
| 663 |
|
| 664 |
X(m_conn_type);
|
| 665 |
+
X(m_forced_inbound);
|
| 666 |
+
stats.m_cpu_time = std::chrono::nanoseconds{m_cpu_time.load()};
|
| 667 |
}
|
| 668 |
#undef X
|
| 669 |
|
|
|
|
| 1691 |
* to forge. In order to partition a node the attacker must be
|
| 1692 |
* simultaneously better at all of them than honest peers.
|
| 1693 |
*/
|
| 1694 |
+
bool CConnman::AttemptToEvictConnection(bool force)
|
| 1695 |
{
|
| 1696 |
std::vector<NodeEvictionCandidate> vEvictionCandidates;
|
| 1697 |
{
|
|
|
|
| 1719 |
vEvictionCandidates.push_back(candidate);
|
| 1720 |
}
|
| 1721 |
}
|
| 1722 |
+
const std::optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates), force);
|
| 1723 |
if (!node_id_to_evict) {
|
| 1724 |
return false;
|
| 1725 |
}
|
|
|
|
| 1775 |
{
|
| 1776 |
int nInbound = 0;
|
| 1777 |
|
| 1778 |
+
const bool inbound_onion = [this, &addr, &addr_bind] {
|
| 1779 |
+
if (!m_onion_binds.empty()) {
|
| 1780 |
+
return std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
|
| 1781 |
+
}
|
| 1782 |
+
if (!m_listenonion || m_normal_binds.empty() || addr_bind != m_normal_binds.front()) return false;
|
| 1783 |
+
// A wildcard first bind shares Tor only with local proxy connections.
|
| 1784 |
+
return !addr_bind.IsBindAny() || addr.IsLocal();
|
| 1785 |
+
}();
|
| 1786 |
|
| 1787 |
// Tor inbound connections do not reveal the peer's actual network address.
|
| 1788 |
// Therefore do not apply address-based whitelist permissions to them.
|
|
|
|
| 1829 |
return;
|
| 1830 |
}
|
| 1831 |
|
| 1832 |
+
bool forced{false};
|
| 1833 |
if (nInbound >= m_max_inbound)
|
| 1834 |
{
|
| 1835 |
+
if (!AttemptToEvictConnection(NetPermissions::HasFlag(permission_flags, NetPermissionFlags::ForceInbound))) {
|
| 1836 |
// No connection to evict, disconnect the new connection
|
| 1837 |
LogDebug(BCLog::NET, "failed to find an eviction candidate - connection dropped (full)\n");
|
| 1838 |
return;
|
| 1839 |
}
|
| 1840 |
+
forced = true;
|
| 1841 |
}
|
| 1842 |
|
| 1843 |
NodeId id = GetNewNodeId();
|
|
|
|
| 1866 |
CNodeOptions{
|
| 1867 |
.permission_flags = permission_flags,
|
| 1868 |
.prefer_evict = discouraged,
|
| 1869 |
+
.forced_inbound = forced,
|
| 1870 |
.recv_flood_size = nReceiveFloodSize,
|
| 1871 |
.use_v2transport = use_v2transport,
|
| 1872 |
});
|
|
|
|
| 1967 |
// Add to reconnection list if appropriate. We don't reconnect right here, because
|
| 1968 |
// the creation of a connection is a blocking operation (up to several seconds),
|
| 1969 |
// and we don't want to hold up the socket handler thread for that long.
|
| 1970 |
+
if (network_active && pnode->m_transport->ShouldReconnectV1() && !DisableV1OnClearnet(pnode->addr.GetNetClass())) {
|
| 1971 |
reconnections_to_add.push_back({
|
| 1972 |
.proxy_override = pnode->m_proxy_override,
|
| 1973 |
.addr_connect = pnode->addr,
|
|
|
|
| 3188 |
if (pnode->fDisconnect)
|
| 3189 |
continue;
|
| 3190 |
|
| 3191 |
+
CpuTimer timer{[pnode](std::chrono::nanoseconds elapsed) { pnode->m_cpu_time.fetch_add(elapsed.count(), std::memory_order_relaxed); }};
|
| 3192 |
+
|
| 3193 |
// Receive messages
|
| 3194 |
bool fMoreNodeWork{m_msgproc->ProcessMessages(*pnode, flagInterruptMsgProc)};
|
| 3195 |
fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
|
|
|
|
| 3782 |
|
| 3783 |
bool CConnman::AddNode(const AddedNodeParams& add)
|
| 3784 |
{
|
| 3785 |
+
const CService resolved{MaybeFlipIPv6toCJDNS(LookupNumeric(add.m_added_node, GetDefaultPort(add.m_added_node)))};
|
|
|
|
|
|
|
| 3786 |
LOCK(m_added_nodes_mutex);
|
| 3787 |
for (const auto& it : m_added_node_params) {
|
| 3788 |
+
if (add.m_added_node == it.m_added_node) return false;
|
| 3789 |
+
if (!resolved.IsValid()) continue;
|
| 3790 |
+
const CService service{MaybeFlipIPv6toCJDNS(LookupNumeric(it.m_added_node, GetDefaultPort(it.m_added_node)))};
|
| 3791 |
+
if (resolved == service) return false;
|
| 3792 |
+
if (resolved.IsCJDNS() && static_cast<CNetAddr>(resolved) == static_cast<CNetAddr>(service)) return false;
|
| 3793 |
}
|
| 3794 |
|
| 3795 |
m_added_node_params.push_back(add);
|
|
|
|
| 4039 |
m_addr_name{addrNameIn.empty() ? addr.ToStringAddrPort() : addrNameIn},
|
| 4040 |
m_dest(addrNameIn),
|
| 4041 |
m_inbound_onion{inbound_onion},
|
| 4042 |
+
m_forced_inbound{node_opts.forced_inbound},
|
| 4043 |
m_prefer_evict{node_opts.prefer_evict},
|
| 4044 |
nKeyedNetGroup{nKeyedNetGroupIn},
|
| 4045 |
m_network_key{network_key},
|