Skip to content
Bitcoin Roots

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},