diff --git a/src/init.cpp b/src/init.cpp index 7f708412fd3..c9363ba96dc 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -578,11 +578,12 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc) argsman.AddArg("-forcednsseed", strprintf("Always query for peer addresses via DNS lookup (default: %u)", DEFAULT_FORCEDNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-listen", strprintf("Accept connections from outside (default: %u if no -proxy, -connect or -maxconnections=0)", DEFAULT_LISTEN), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-listenonion", strprintf("Automatically create Tor onion service (default: %d)", DEFAULT_LISTEN_ONION), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-maxconnections=", strprintf("Maintain at most automatic connections to peers (default: %u). %u slots of these are reserved for outgoing connections, %u percent of the remaining ones can support transaction relay. " + argsman.AddArg("-maxconnections=", strprintf("Maintain at most automatic connections to peers (default: %u). %u slots of these are reserved for outgoing connections. See -inboundrelaypercent for more information about limits applied to transaction relay inbound peers. " "This limit does not apply to connections manually added via -addnode or the addnode RPC, which have a separate limit of %u. " "It does not apply to short-lived private broadcast connections either, which have a separate limit of %u.", - DEFAULT_MAX_PEER_CONNECTIONS, MAX_OUTBOUND_FULL_RELAY_CONNECTIONS + MAX_BLOCK_RELAY_ONLY_CONNECTIONS + MAX_FEELER_CONNECTIONS, static_cast(100 * FULL_RELAY_INBOUND_PCT), MAX_ADDNODE_CONNECTIONS, MAX_PRIVATE_BROADCAST_CONNECTIONS), + DEFAULT_MAX_PEER_CONNECTIONS, MAX_OUTBOUND_FULL_RELAY_CONNECTIONS + MAX_BLOCK_RELAY_ONLY_CONNECTIONS + MAX_FEELER_CONNECTIONS, MAX_ADDNODE_CONNECTIONS, MAX_PRIVATE_BROADCAST_CONNECTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); + argsman.AddArg("-inboundrelaypercent=", strprintf("Permit a maximum percent of inbound connections to relay transactions, to limit memory utilization (0 to 100, default: %u).", DEFAULT_FULL_RELAY_INBOUND_PCT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-maxreceivebuffer=", strprintf("Maximum per-connection receive buffer, *1000 bytes (default: %u)", DEFAULT_MAXRECEIVEBUFFER), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-maxsendbuffer=", strprintf("Maximum per-connection memory usage for the send buffer, *1000 bytes (default: %u)", DEFAULT_MAXSENDBUFFER), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-maxuploadtarget=", strprintf("Tries to keep outbound traffic under the given target per 24h. Limit does not apply to peers with 'download' permission or blocks created within past week. 0 = no limit (default: %s). Optional suffix units [k|K|m|M|g|G|t|T] (default: M). Lowercase is 1000 base while uppercase is 1024 base", DEFAULT_MAX_UPLOAD_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); @@ -2121,6 +2122,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) CConnman::Options connOptions; connOptions.m_local_services = g_local_services; connOptions.m_max_automatic_connections = nMaxConnections; + connOptions.m_full_relay_inbound_percent = std::clamp(args.GetIntArg("-inboundrelaypercent", DEFAULT_FULL_RELAY_INBOUND_PCT), 0, 100); connOptions.uiInterface = &uiInterface; connOptions.m_banman = node.banman.get(); connOptions.m_msgproc = node.peerman.get(); diff --git a/src/net.h b/src/net.h index fa5768cb279..f1814120a31 100644 --- a/src/net.h +++ b/src/net.h @@ -79,8 +79,8 @@ static constexpr size_t MAX_PRIVATE_BROADCAST_CONNECTIONS{64}; static const bool DEFAULT_LISTEN = true; /** The maximum number of peer connections to maintain. */ static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS{200}; -/** Percentage of inbound connection slots that tx-relaying peers can use */ -static const int FULL_RELAY_INBOUND_PCT{50}; +/** Default percentage of inbound connection slots that tx-relaying peers can use */ +static const int DEFAULT_FULL_RELAY_INBOUND_PCT{50}; /** The default for -maxuploadtarget. 0 = Unlimited */ static const std::string DEFAULT_MAX_UPLOAD_TARGET{"0M"}; /** Default for blocks only*/ @@ -1089,6 +1089,7 @@ public: { ServiceFlags m_local_services = NODE_NONE; int m_max_automatic_connections = DEFAULT_MAX_PEER_CONNECTIONS; + int m_full_relay_inbound_percent = DEFAULT_FULL_RELAY_INBOUND_PCT; CClientUIInterface* uiInterface = nullptr; NetEventsInterface* m_msgproc = nullptr; BanMan* m_banman = nullptr; @@ -1124,7 +1125,7 @@ public: m_max_outbound_block_relay = std::min(MAX_BLOCK_RELAY_ONLY_CONNECTIONS, m_max_automatic_connections - m_max_outbound_full_relay); m_max_automatic_outbound = m_max_outbound_full_relay + m_max_outbound_block_relay + m_max_feeler; m_max_inbound = std::max(0, m_max_automatic_connections - m_max_automatic_outbound); - m_max_inbound_full_relay = std::max(0, static_cast(FULL_RELAY_INBOUND_PCT / 100.0 * m_max_inbound)); + m_max_inbound_full_relay = std::max(0, static_cast(connOptions.m_full_relay_inbound_percent / 100.0 * m_max_inbound)); m_use_addrman_outgoing = connOptions.m_use_addrman_outgoing; m_client_interface = connOptions.uiInterface; m_banman = connOptions.m_banman; diff --git a/test/functional/p2p_connection_limits.py b/test/functional/p2p_connection_limits.py index 20e34cabf57..338f8f74f91 100755 --- a/test/functional/p2p_connection_limits.py +++ b/test/functional/p2p_connection_limits.py @@ -58,6 +58,16 @@ class P2PConnectionLimits(BitcoinTestFramework): self.nodes[0].add_p2p_connection(P2PInterface(), send_version=False, wait_for_verack=False, expect_success=False) self.wait_until(lambda: len(node.getpeerinfo()) == 2) + self.log.info('Test different values of inboundrelaypercent') + self.restart_node(0, ['-maxconnections=13', '-inboundrelaypercent=0']) + with node.assert_debug_log(['failed to find a tx-relaying eviction candidate - connection dropped'], timeout=2): + self.nodes[0].add_p2p_connection(P2PInterface(), expect_success=False, wait_for_verack=False) + + self.restart_node(0, ['-maxconnections=13', '-inboundrelaypercent=100']) + node.add_p2p_connection(P2PInterface()) + node.add_p2p_connection(P2PInterface()) + self.wait_until(lambda: len(node.getpeerinfo()) == 2) + if __name__ == '__main__': P2PConnectionLimits(__file__).main() diff --git a/test/functional/p2p_opportunistic_1p1c.py b/test/functional/p2p_opportunistic_1p1c.py index 6841d7c3a14..156ffd9a00b 100755 --- a/test/functional/p2p_opportunistic_1p1c.py +++ b/test/functional/p2p_opportunistic_1p1c.py @@ -76,7 +76,7 @@ class PackageRelayTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 self.extra_args = [[ - "-maxmempool=5","-maxconnections=150" + "-maxmempool=5","-inboundrelaypercent=100" ]] def create_tx_below_mempoolminfee(self, wallet, utxo_to_spend=None):