Skip to content
Bitcoin Roots

v29.4-roots.3 · Commit 3: [PATCH 03/30] policy: restore conservative relay and network controls

src/net.cpp

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

File metadata
index 7684877ec352cfbee891ee61501367d1169e88d5..05ee7224226c339bbe7ad04c8fdf1a4dedc199bd 100644

Download original patch · Release notes

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