Skip to content
Bitcoin Roots

v30.3-roots.1 · Commit 3: [PATCH 03/68] feat(policy): preserve Roots relay and network controls on Core 30.3

src/net.cpp

Before: src/net.cpp · After: src/net.cpp

File metadata
index 50988114d0b137dd47b388c2678484376612d806..b29cb951b141922e1a5b3c75fc29b7c55ff154df 100644

Download original patch · Release notes

Diff rows 1–377 of 377. 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
@@ -108,7 +108,7 @@ const std::string NET_MESSAGE_TYPE_OTHER = "*other*";
108
 
109
  static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8]
110
  static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // SHA256("localhostnonce")[0:8]
111
- static const uint64_t RANDOMIZER_ID_ADDRCACHE = 0x1cf2e4ddd306dda9ULL; // SHA256("addrcache")[0:8]
112
  //
113
  // Global state variables
114
  //
@@ -221,7 +221,7 @@ CService GetLocalAddress(const CNode& peer)
221
  return GetLocal(peer).value_or(CService{CNetAddr(), GetListenPort()});
222
  }
223
 
224
- static int GetnScore(const CService& addr)
225
  {
226
  LOCK(g_maplocalhost_mutex);
227
  const auto it = mapLocalHost.find(addr);
@@ -283,7 +283,8 @@ bool AddLocal(const CService& addr_, int nScore)
283
  if (!fDiscover && nScore < LOCAL_MANUAL)
284
  return false;
285
 
286
- if (!g_reachable_nets.Contains(addr))
 
287
  return false;
288
 
289
  LogPrintf("AddLocal(%s,%i)\n", addr.ToStringAddrPort(), nScore);
@@ -308,9 +309,11 @@ bool AddLocal(const CNetAddr &addr, int nScore)
308
 
309
  void RemoveLocal(const CService& addr)
310
  {
311
- LOCK(g_maplocalhost_mutex);
312
- LogPrintf("RemoveLocal(%s)\n", addr.ToStringAddrPort());
313
- mapLocalHost.erase(addr);
 
 
314
  }
315
 
316
  /** vote for a local address */
@@ -319,7 +322,9 @@ bool SeenLocal(const CService& addr)
319
  LOCK(g_maplocalhost_mutex);
320
  const auto it = mapLocalHost.find(addr);
321
  if (it == mapLocalHost.end()) return false;
322
- ++it->second.nScore;
 
 
323
  return true;
324
  }
325
 
@@ -462,6 +467,9 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
462
  std::unique_ptr<i2p::sam::Session> i2p_transient_session;
463
 
464
  for (auto& target_addr: connect_to) {
 
 
 
465
  if (target_addr.IsValid()) {
466
  const bool use_proxy{GetProxy(target_addr.GetNetwork(), proxy)};
467
  bool proxyConnectionFailed = false;
@@ -521,8 +529,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
521
  }
522
 
523
  NetPermissionFlags permission_flags = NetPermissionFlags::None;
524
- std::vector<NetWhitelistPermissions> whitelist_permissions = conn_type == ConnectionType::MANUAL ? vWhitelistedRangeOutgoing : std::vector<NetWhitelistPermissions>{};
525
- AddWhitelistPermissionFlags(permission_flags, target_addr, whitelist_permissions);
526
 
527
  // Add node
528
  NodeId id = GetNewNodeId();
@@ -530,6 +537,13 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
530
  if (!addr_bind.IsValid()) {
531
  addr_bind = GetBindAddress(*sock);
532
  }
 
 
 
 
 
 
 
533
  CNode* pnode = new CNode(id,
534
  std::move(sock),
535
  target_addr,
@@ -539,6 +553,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
539
  pszDest ? pszDest : "",
540
  conn_type,
541
  /*inbound_onion=*/false,
 
542
  CNodeOptions{
543
  .permission_flags = permission_flags,
544
  .i2p_sam_session = std::move(i2p_transient_session),
@@ -586,6 +601,7 @@ void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, std::optio
586
  if (whitelist_relay) NetPermissions::AddFlag(flags, NetPermissionFlags::Relay);
587
  NetPermissions::AddFlag(flags, NetPermissionFlags::Mempool);
588
  NetPermissions::AddFlag(flags, NetPermissionFlags::NoBan);
 
589
  }
590
  }
591
 
@@ -650,6 +666,7 @@ void CNode::CopyStats(CNodeStats& stats)
650
  if (info.session_id) stats.m_session_id = HexStr(*info.session_id);
651
  }
652
  X(m_permission_flags);
 
653
 
654
  X(m_last_ping_time);
655
  X(m_min_ping_time);
@@ -659,6 +676,8 @@ void CNode::CopyStats(CNodeStats& stats)
659
  stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToStringAddrPort() : "";
660
 
661
  X(m_conn_type);
 
 
662
  }
663
  #undef X
664
 
@@ -1684,7 +1703,7 @@ std::pair<size_t, bool> CConnman::SocketSendData(CNode& node) const
1684
  * to forge. In order to partition a node the attacker must be
1685
  * simultaneously better at all of them than honest peers.
1686
  */
1687
- bool CConnman::AttemptToEvictConnection()
1688
  {
1689
  std::vector<NodeEvictionCandidate> vEvictionCandidates;
1690
  {
@@ -1712,7 +1731,7 @@ bool CConnman::AttemptToEvictConnection()
1712
  vEvictionCandidates.push_back(candidate);
1713
  }
1714
  }
1715
- const std::optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates));
1716
  if (!node_id_to_evict) {
1717
  return false;
1718
  }
@@ -1768,7 +1787,26 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
1768
  {
1769
  int nInbound = 0;
1770
 
1771
- const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1772
 
1773
  // Tor inbound connections do not reveal the peer's actual network address.
1774
  // Therefore do not apply address-based whitelist permissions to them.
@@ -1815,13 +1853,19 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
1815
  return;
1816
  }
1817
 
 
1818
  if (nInbound >= m_max_inbound)
1819
  {
1820
- if (!AttemptToEvictConnection()) {
 
 
1821
  // No connection to evict, disconnect the new connection
1822
  LogDebug(BCLog::NET, "failed to find an eviction candidate - connection dropped (full)\n");
1823
  return;
1824
  }
 
 
 
1825
  }
1826
 
1827
  NodeId id = GetNewNodeId();
@@ -1832,6 +1876,11 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
1832
  ServiceFlags local_services = GetLocalServices();
1833
  const bool use_v2transport(local_services & NODE_P2P_V2);
1834
 
 
 
 
 
 
1835
  CNode* pnode = new CNode(id,
1836
  std::move(sock),
1837
  CAddress{addr, NODE_NONE},
@@ -1841,9 +1890,11 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
1841
  /*addrNameIn=*/"",
1842
  ConnectionType::INBOUND,
1843
  inbound_onion,
 
1844
  CNodeOptions{
1845
  .permission_flags = permission_flags,
1846
  .prefer_evict = discouraged,
 
1847
  .recv_flood_size = nReceiveFloodSize,
1848
  .use_v2transport = use_v2transport,
1849
  });
@@ -1937,7 +1988,7 @@ void CConnman::DisconnectNodes()
1937
  // Add to reconnection list if appropriate. We don't reconnect right here, because
1938
  // the creation of a connection is a blocking operation (up to several seconds),
1939
  // and we don't want to hold up the socket handler thread for that long.
1940
- if (network_active && pnode->m_transport->ShouldReconnectV1()) {
1941
  reconnections_to_add.push_back({
1942
  .addr_connect = pnode->addr,
1943
  .grant = std::move(pnode->grantOutbound),
@@ -1996,16 +2047,15 @@ void CConnman::NotifyNumConnectionsChanged()
1996
  }
1997
  }
1998
 
1999
- bool CConnman::ShouldRunInactivityChecks(const CNode& node, std::chrono::seconds now) const
2000
  {
2001
  return node.m_connected + m_peer_connect_timeout < now;
2002
  }
2003
 
2004
- bool CConnman::InactivityCheck(const CNode& node) const
2005
  {
2006
  // Tests that see disconnects after using mocktime can start nodes with a
2007
  // large timeout. For example, -peertimeout=999999999.
2008
- const auto now{GetTime<std::chrono::seconds>()};
2009
  const auto last_send{node.m_last_send.load()};
2010
  const auto last_recv{node.m_last_recv.load()};
2011
 
@@ -2029,7 +2079,7 @@ bool CConnman::InactivityCheck(const CNode& node) const
2029
 
2030
  if (now > last_send + TIMEOUT_INTERVAL) {
2031
  LogDebug(BCLog::NET,
2032
- "socket sending timeout: %is, %s\n", count_seconds(now - last_send),
2033
  node.DisconnectMsg(fLogIPs)
2034
  );
2035
  return true;
@@ -2037,7 +2087,7 @@ bool CConnman::InactivityCheck(const CNode& node) const
2037
 
2038
  if (now > last_recv + TIMEOUT_INTERVAL) {
2039
  LogDebug(BCLog::NET,
2040
- "socket receive timeout: %is, %s\n", count_seconds(now - last_recv),
2041
  node.DisconnectMsg(fLogIPs)
2042
  );
2043
  return true;
@@ -2119,6 +2169,8 @@ void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
2119
  {
2120
  AssertLockNotHeld(m_total_bytes_sent_mutex);
2121
 
 
 
2122
  for (CNode* pnode : nodes) {
2123
  if (interruptNet)
2124
  return;
@@ -2209,7 +2261,7 @@ void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
2209
  }
2210
  }
2211
 
2212
- if (InactivityCheck(*pnode)) pnode->fDisconnect = true;
2213
  }
2214
  }
2215
 
@@ -2500,6 +2552,11 @@ bool CConnman::MultipleManualOrFullOutboundConns(Network net) const
2500
  return m_network_conn_counts[net] > 1;
2501
  }
2502
 
 
 
 
 
 
2503
  bool CConnman::MaybePickPreferredNetwork(std::optional<Network>& network)
2504
  {
2505
  std::array<Network, 5> nets{NET_IPV4, NET_IPV6, NET_ONION, NET_I2P, NET_CJDNS};
@@ -3052,6 +3109,8 @@ void CConnman::ThreadMessageHandler()
3052
  if (pnode->fDisconnect)
3053
  continue;
3054
 
 
 
3055
  // Receive messages
3056
  bool fMoreNodeWork = m_msgproc->ProcessMessages(pnode, flagInterruptMsgProc);
3057
  fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
@@ -3289,7 +3348,29 @@ bool CConnman::InitBinds(const Options& options)
3289
  inaddr_any.s_addr = htonl(INADDR_ANY);
3290
  const CService ipv4_any{inaddr_any, GetListenPort()}; // 0.0.0.0
3291
  if (!Bind(ipv4_any, BF_REPORT_ERROR, NetPermissionFlags::None)) {
3292
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3293
  }
3294
  }
3295
  return true;
@@ -3460,6 +3541,8 @@ void CConnman::StopThreads()
3460
 
3461
  void CConnman::StopNodes()
3462
  {
 
 
3463
  if (fAddressesInitialized) {
3464
  DumpAddresses();
3465
  fAddressesInitialized = false;
@@ -3487,6 +3570,7 @@ void CConnman::StopNodes()
3487
  DeleteNode(pnode);
3488
  }
3489
  m_nodes_disconnected.clear();
 
3490
  vhListenSocket.clear();
3491
  semOutbound.reset();
3492
  semAddnode.reset();
@@ -3519,15 +3603,9 @@ std::vector<CAddress> CConnman::GetAddressesUnsafe(size_t max_addresses, size_t
3519
  std::vector<CAddress> CConnman::GetAddresses(CNode& requestor, size_t max_addresses, size_t max_pct)
3520
  {
3521
  auto local_socket_bytes = requestor.addrBind.GetAddrBytes();
3522
- uint64_t cache_id = GetDeterministicRandomizer(RANDOMIZER_ID_ADDRCACHE)
3523
- .Write(requestor.ConnectedThroughNetwork())
3524
- .Write(local_socket_bytes)
3525
- // For outbound connections, the port of the bound address is randomly
3526
- // assigned by the OS and would therefore not be useful for seeding.
3527
- .Write(requestor.IsInboundConn() ? requestor.addrBind.GetPort() : 0)
3528
- .Finalize();
3529
  const auto current_time = GetTime<std::chrono::microseconds>();
3530
- auto r = m_addr_response_caches.emplace(cache_id, CachedAddrResponse{});
3531
  CachedAddrResponse& cache_entry = r.first->second;
3532
  if (cache_entry.m_cache_entry_expiration < current_time) { // If emplace() added new one it has expiration 0.
3533
  cache_entry.m_addrs_response_cache = GetAddressesUnsafe(max_addresses, max_pct, /*network=*/std::nullopt);
@@ -3563,12 +3641,17 @@ std::vector<CAddress> CConnman::GetAddresses(CNode& requestor, size_t max_addres
3563
 
3564
  bool CConnman::AddNode(const AddedNodeParams& add)
3565
  {
3566
- const CService resolved(LookupNumeric(add.m_added_node, GetDefaultPort(add.m_added_node)));
3567
- const bool resolved_is_valid{resolved.IsValid()};
3568
 
3569
  LOCK(m_added_nodes_mutex);
3570
  for (const auto& it : m_added_node_params) {
3571
- 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;
 
 
 
 
 
3572
  }
3573
 
3574
  m_added_node_params.push_back(add);
@@ -3804,6 +3887,7 @@ CNode::CNode(NodeId idIn,
3804
  const std::string& addrNameIn,
3805
  ConnectionType conn_type_in,
3806
  bool inbound_onion,
 
3807
  CNodeOptions&& node_opts)
3808
  : m_transport{MakeTransport(idIn, node_opts.use_v2transport, conn_type_in == ConnectionType::INBOUND)},
3809
  m_permission_flags{node_opts.permission_flags},
@@ -3815,7 +3899,9 @@ CNode::CNode(NodeId idIn,
3815
  m_dest(addrNameIn),
3816
  m_inbound_onion{inbound_onion},
3817
  m_prefer_evict{node_opts.prefer_evict},
 
3818
  nKeyedNetGroup{nKeyedNetGroupIn},
 
3819
  m_conn_type{conn_type_in},
3820
  id{idIn},
3821
  nLocalHostNonce{nLocalHostNonceIn},
@@ -3877,7 +3963,7 @@ void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
3877
  AssertLockNotHeld(m_total_bytes_sent_mutex);
3878
  size_t nMessageSize = msg.data.size();
3879
  LogDebug(BCLog::NET, "sending %s (%d bytes) peer=%d\n", msg.m_type, nMessageSize, pnode->GetId());
3880
- if (gArgs.GetBoolArg("-capturemessages", false)) {
3881
  CaptureMessage(pnode->addr, msg.m_type, msg.data, /*is_incoming=*/false);
3882
  }
3883
 
 
108
 
109
  static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8]
110
  static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // SHA256("localhostnonce")[0:8]
111
+ static const uint64_t RANDOMIZER_ID_NETWORKKEY = 0x0e8a2b136c592a7dULL; // SHA256("networkkey")[0:8]
112
  //
113
  // Global state variables
114
  //
 
221
  return GetLocal(peer).value_or(CService{CNetAddr(), GetListenPort()});
222
  }
223
 
224
+ int GetnScore(const CService& addr)
225
  {
226
  LOCK(g_maplocalhost_mutex);
227
  const auto it = mapLocalHost.find(addr);
 
283
  if (!fDiscover && nScore < LOCAL_MANUAL)
284
  return false;
285
 
286
+ // IPv4 and IPv6 cannot be connected to unless their networks are reachable, but Tor is not necessarily bidirectional
287
+ if (!(g_reachable_nets.Contains(addr) || addr.IsTor()))
288
  return false;
289
 
290
  LogPrintf("AddLocal(%s,%i)\n", addr.ToStringAddrPort(), nScore);
 
309
 
310
  void RemoveLocal(const CService& addr)
311
  {
312
+ {
313
+ LOCK(g_maplocalhost_mutex);
314
+ LogPrintf("RemoveLocal(%s)\n", addr.ToStringAddrPort());
315
+ mapLocalHost.erase(addr);
316
+ }
317
  }
318
 
319
  /** vote for a local address */
 
322
  LOCK(g_maplocalhost_mutex);
323
  const auto it = mapLocalHost.find(addr);
324
  if (it == mapLocalHost.end()) return false;
325
+ if (it->second.nScore < std::numeric_limits<int>::max()) {
326
+ ++it->second.nScore;
327
+ }
328
  return true;
329
  }
330
 
 
467
  std::unique_ptr<i2p::sam::Session> i2p_transient_session;
468
 
469
  for (auto& target_addr: connect_to) {
470
+ if (DisableV1OnClearnet(target_addr.GetNetClass()) && !use_v2transport) {
471
+ continue;
472
+ }
473
  if (target_addr.IsValid()) {
474
  const bool use_proxy{GetProxy(target_addr.GetNetwork(), proxy)};
475
  bool proxyConnectionFailed = false;
 
529
  }
530
 
531
  NetPermissionFlags permission_flags = NetPermissionFlags::None;
532
+ AddWhitelistPermissionFlags(permission_flags, target_addr, vWhitelistedRangeOutgoing);
 
533
 
534
  // Add node
535
  NodeId id = GetNewNodeId();
 
537
  if (!addr_bind.IsValid()) {
538
  addr_bind = GetBindAddress(*sock);
539
  }
540
+ uint64_t network_id = GetDeterministicRandomizer(RANDOMIZER_ID_NETWORKKEY)
541
+ .Write(target_addr.GetNetClass())
542
+ .Write(addr_bind.GetAddrBytes())
543
+ // For outbound connections, the port of the bound address is randomly
544
+ // assigned by the OS and would therefore not be useful for seeding.
545
+ .Write(0)
546
+ .Finalize();
547
  CNode* pnode = new CNode(id,
548
  std::move(sock),
549
  target_addr,
 
553
  pszDest ? pszDest : "",
554
  conn_type,
555
  /*inbound_onion=*/false,
556
+ network_id,
557
  CNodeOptions{
558
  .permission_flags = permission_flags,
559
  .i2p_sam_session = std::move(i2p_transient_session),
 
601
  if (whitelist_relay) NetPermissions::AddFlag(flags, NetPermissionFlags::Relay);
602
  NetPermissions::AddFlag(flags, NetPermissionFlags::Mempool);
603
  NetPermissions::AddFlag(flags, NetPermissionFlags::NoBan);
604
+ NetPermissions::AddFlag(flags, NetPermissionFlags::Addr);
605
  }
606
  }
607
 
 
666
  if (info.session_id) stats.m_session_id = HexStr(*info.session_id);
667
  }
668
  X(m_permission_flags);
669
+ X(m_forced_inbound);
670
 
671
  X(m_last_ping_time);
672
  X(m_min_ping_time);
 
676
  stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToStringAddrPort() : "";
677
 
678
  X(m_conn_type);
679
+
680
+ X(m_cpu_time);
681
  }
682
  #undef X
683
 
 
1703
  * to forge. In order to partition a node the attacker must be
1704
  * simultaneously better at all of them than honest peers.
1705
  */
1706
+ bool CConnman::AttemptToEvictConnection(bool force)
1707
  {
1708
  std::vector<NodeEvictionCandidate> vEvictionCandidates;
1709
  {
 
1731
  vEvictionCandidates.push_back(candidate);
1732
  }
1733
  }
1734
+ const std::optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates), force);
1735
  if (!node_id_to_evict) {
1736
  return false;
1737
  }
 
1787
  {
1788
  int nInbound = 0;
1789
 
1790
+ const bool inbound_onion = [this, &addr, &addr_bind]{
1791
+ if (m_onion_binds.empty()) {
1792
+ if (!m_listenonion) {
1793
+ // If -listenonion=0, assume we do not have inbound Tor connections on non-onion listeners
1794
+ return false;
1795
+ }
1796
+ // Tor connections are coming in on the first -bind
1797
+ if ((!m_normal_binds.empty()) && addr_bind == m_normal_binds.front()) {
1798
+ if (addr_bind.IsBindAny()) {
1799
+ // Tor connections should have a source IP that is local
1800
+ return addr.IsLocal();
1801
+ }
1802
+ // Otherwise, the source IP is unpredictable, so assume anything could be onion
1803
+ return true;
1804
+ }
1805
+ return false;
1806
+ } else {
1807
+ return std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
1808
+ }
1809
+ }();
1810
 
1811
  // Tor inbound connections do not reveal the peer's actual network address.
1812
  // Therefore do not apply address-based whitelist permissions to them.
 
1853
  return;
1854
  }
1855
 
1856
+ bool forced{false};
1857
  if (nInbound >= m_max_inbound)
1858
  {
1859
+ // If the inbound connection attempt is granted ForceInbound permission, try a little harder
1860
+ // to make room by evicting a peer we may not have otherwise evicted.
1861
+ if (!AttemptToEvictConnection(NetPermissions::HasFlag(permission_flags, NetPermissionFlags::ForceInbound))) {
1862
  // No connection to evict, disconnect the new connection
1863
  LogDebug(BCLog::NET, "failed to find an eviction candidate - connection dropped (full)\n");
1864
  return;
1865
  }
1866
+
1867
+ // We kicked someone out
1868
+ forced = true;
1869
  }
1870
 
1871
  NodeId id = GetNewNodeId();
 
1876
  ServiceFlags local_services = GetLocalServices();
1877
  const bool use_v2transport(local_services & NODE_P2P_V2);
1878
 
1879
+ uint64_t network_id = GetDeterministicRandomizer(RANDOMIZER_ID_NETWORKKEY)
1880
+ .Write(inbound_onion ? NET_ONION : addr.GetNetClass())
1881
+ .Write(addr_bind.GetAddrBytes())
1882
+ .Write(addr_bind.GetPort()) // inbound connections use bind port
1883
+ .Finalize();
1884
  CNode* pnode = new CNode(id,
1885
  std::move(sock),
1886
  CAddress{addr, NODE_NONE},
 
1890
  /*addrNameIn=*/"",
1891
  ConnectionType::INBOUND,
1892
  inbound_onion,
1893
+ network_id,
1894
  CNodeOptions{
1895
  .permission_flags = permission_flags,
1896
  .prefer_evict = discouraged,
1897
+ .forced_inbound = forced,
1898
  .recv_flood_size = nReceiveFloodSize,
1899
  .use_v2transport = use_v2transport,
1900
  });
 
1988
  // Add to reconnection list if appropriate. We don't reconnect right here, because
1989
  // the creation of a connection is a blocking operation (up to several seconds),
1990
  // and we don't want to hold up the socket handler thread for that long.
1991
+ if (network_active && pnode->m_transport->ShouldReconnectV1() && !DisableV1OnClearnet(pnode->addr.GetNetClass())) {
1992
  reconnections_to_add.push_back({
1993
  .addr_connect = pnode->addr,
1994
  .grant = std::move(pnode->grantOutbound),
 
2047
  }
2048
  }
2049
 
2050
+ bool CConnman::ShouldRunInactivityChecks(const CNode& node, std::chrono::microseconds now) const
2051
  {
2052
  return node.m_connected + m_peer_connect_timeout < now;
2053
  }
2054
 
2055
+ bool CConnman::InactivityCheck(const CNode& node, std::chrono::microseconds now) const
2056
  {
2057
  // Tests that see disconnects after using mocktime can start nodes with a
2058
  // large timeout. For example, -peertimeout=999999999.
 
2059
  const auto last_send{node.m_last_send.load()};
2060
  const auto last_recv{node.m_last_recv.load()};
2061
 
 
2079
 
2080
  if (now > last_send + TIMEOUT_INTERVAL) {
2081
  LogDebug(BCLog::NET,
2082
+ "socket sending timeout: %is, %s\n", Ticks<std::chrono::seconds>(now - last_send),
2083
  node.DisconnectMsg(fLogIPs)
2084
  );
2085
  return true;
 
2087
 
2088
  if (now > last_recv + TIMEOUT_INTERVAL) {
2089
  LogDebug(BCLog::NET,
2090
+ "socket receive timeout: %is, %s\n", Ticks<std::chrono::seconds>(now - last_recv),
2091
  node.DisconnectMsg(fLogIPs)
2092
  );
2093
  return true;
 
2169
  {
2170
  AssertLockNotHeld(m_total_bytes_sent_mutex);
2171
 
2172
+ auto now = GetTime<std::chrono::microseconds>();
2173
+
2174
  for (CNode* pnode : nodes) {
2175
  if (interruptNet)
2176
  return;
 
2261
  }
2262
  }
2263
 
2264
+ if (InactivityCheck(*pnode, now)) pnode->fDisconnect = true;
2265
  }
2266
  }
2267
 
 
2552
  return m_network_conn_counts[net] > 1;
2553
  }
2554
 
2555
+ bool CConnman::DisableV1OnClearnet(Network net) const
2556
+ {
2557
+ return disable_v1conn_clearnet && (net == NET_IPV4 || net == NET_IPV6);
2558
+ }
2559
+
2560
  bool CConnman::MaybePickPreferredNetwork(std::optional<Network>& network)
2561
  {
2562
  std::array<Network, 5> nets{NET_IPV4, NET_IPV6, NET_ONION, NET_I2P, NET_CJDNS};
 
3109
  if (pnode->fDisconnect)
3110
  continue;
3111
 
3112
+ CpuTimer timer{[&pnode](std::chrono::nanoseconds elapsed) { pnode->m_cpu_time += elapsed; }};
3113
+
3114
  // Receive messages
3115
  bool fMoreNodeWork = m_msgproc->ProcessMessages(pnode, flagInterruptMsgProc);
3116
  fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
 
3348
  inaddr_any.s_addr = htonl(INADDR_ANY);
3349
  const CService ipv4_any{inaddr_any, GetListenPort()}; // 0.0.0.0
3350
  if (!Bind(ipv4_any, BF_REPORT_ERROR, NetPermissionFlags::None)) {
3351
+ int defaultPort = Params().GetDefaultPort();
3352
+ // If listening failed and another port than the standard port was specified,
3353
+ // ask if the user wants to connect via the standard port for the network instead
3354
+ if (GetListenPort() != defaultPort) {
3355
+ bool fRet = uiInterface.ThreadSafeQuestion(
3356
+ strprintf(_("Do you want to use the standard network port for %s (port %s) instead?"), CLIENT_NAME, defaultPort),
3357
+ strprintf(_("Listen on port %s failed."), GetListenPort()).translated,
3358
+ "", CClientUIInterface::MSG_INFORMATION | CClientUIInterface::MODAL | CClientUIInterface::BTN_OK | CClientUIInterface::BTN_ABORT);
3359
+
3360
+ if (fRet) {
3361
+ // FIXME: Unbind IPv6 on the other port
3362
+
3363
+ gArgs.ForceSetArg("-port", defaultPort);
3364
+ // Attempt to use standard port
3365
+ struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
3366
+ Bind(CService(inaddr6_any, defaultPort), BF_NONE, NetPermissionFlags::None);
3367
+ struct in_addr inaddr_any;
3368
+ inaddr_any.s_addr = INADDR_ANY;
3369
+ if (!Bind(CService(inaddr_any, defaultPort), BF_REPORT_ERROR, NetPermissionFlags::None)) {
3370
+ return false;
3371
+ }
3372
+ }
3373
+ }
3374
  }
3375
  }
3376
  return true;
 
3541
 
3542
  void CConnman::StopNodes()
3543
  {
3544
+ AssertLockNotHeld(m_reconnections_mutex);
3545
+
3546
  if (fAddressesInitialized) {
3547
  DumpAddresses();
3548
  fAddressesInitialized = false;
 
3570
  DeleteNode(pnode);
3571
  }
3572
  m_nodes_disconnected.clear();
3573
+ WITH_LOCK(m_reconnections_mutex, m_reconnections.clear());
3574
  vhListenSocket.clear();
3575
  semOutbound.reset();
3576
  semAddnode.reset();
 
3603
  std::vector<CAddress> CConnman::GetAddresses(CNode& requestor, size_t max_addresses, size_t max_pct)
3604
  {
3605
  auto local_socket_bytes = requestor.addrBind.GetAddrBytes();
3606
+ uint64_t network_id = requestor.m_network_key;
 
 
 
 
 
 
3607
  const auto current_time = GetTime<std::chrono::microseconds>();
3608
+ auto r = m_addr_response_caches.emplace(network_id, CachedAddrResponse{});
3609
  CachedAddrResponse& cache_entry = r.first->second;
3610
  if (cache_entry.m_cache_entry_expiration < current_time) { // If emplace() added new one it has expiration 0.
3611
  cache_entry.m_addrs_response_cache = GetAddressesUnsafe(max_addresses, max_pct, /*network=*/std::nullopt);
 
3641
 
3642
  bool CConnman::AddNode(const AddedNodeParams& add)
3643
  {
3644
+ const CService resolved{MaybeFlipIPv6toCJDNS(LookupNumeric(add.m_added_node, GetDefaultPort(add.m_added_node)))};
3645
+ const bool resolved_invalid{!resolved.IsValid()};
3646
 
3647
  LOCK(m_added_nodes_mutex);
3648
  for (const auto& it : m_added_node_params) {
3649
+ if (add.m_added_node == it.m_added_node) return false;
3650
+ if (resolved_invalid) continue;
3651
+ const CService service{MaybeFlipIPv6toCJDNS(LookupNumeric(it.m_added_node, GetDefaultPort(it.m_added_node)))};
3652
+ if (resolved == service) return false;
3653
+ // Check if CJDNS address matches regardless of port to detect already-connected inbound peers.
3654
+ if (resolved.IsCJDNS() && static_cast<CNetAddr>(resolved) == static_cast<CNetAddr>(service)) return false;
3655
  }
3656
 
3657
  m_added_node_params.push_back(add);
 
3887
  const std::string& addrNameIn,
3888
  ConnectionType conn_type_in,
3889
  bool inbound_onion,
3890
+ uint64_t network_key,
3891
  CNodeOptions&& node_opts)
3892
  : m_transport{MakeTransport(idIn, node_opts.use_v2transport, conn_type_in == ConnectionType::INBOUND)},
3893
  m_permission_flags{node_opts.permission_flags},
 
3899
  m_dest(addrNameIn),
3900
  m_inbound_onion{inbound_onion},
3901
  m_prefer_evict{node_opts.prefer_evict},
3902
+ m_forced_inbound{node_opts.forced_inbound},
3903
  nKeyedNetGroup{nKeyedNetGroupIn},
3904
+ m_network_key{network_key},
3905
  m_conn_type{conn_type_in},
3906
  id{idIn},
3907
  nLocalHostNonce{nLocalHostNonceIn},
 
3963
  AssertLockNotHeld(m_total_bytes_sent_mutex);
3964
  size_t nMessageSize = msg.data.size();
3965
  LogDebug(BCLog::NET, "sending %s (%d bytes) peer=%d\n", msg.m_type, nMessageSize, pnode->GetId());
3966
+ if (m_capture_messages) {
3967
  CaptureMessage(pnode->addr, msg.m_type, msg.data, /*is_incoming=*/false);
3968
  }
3969