From 01dad4efe2b38b7a71c96b6222147f395e0c11d9 Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Thu, 14 Dec 2023 14:34:08 +0100 Subject: [PATCH] net: introduce a new connection type for private broadcast We will open a short-lived connection to a random Tor or I2P peer, send our transaction to that peer and close the connection. --- src/bitcoin-cli.cpp | 2 ++ src/net.cpp | 2 ++ src/net.h | 8 ++++++++ src/node/connection_types.cpp | 2 ++ src/node/connection_types.h | 7 +++++++ src/qt/guiutil.cpp | 2 ++ src/qt/rpcconsole.cpp | 5 ++++- src/rpc/net.cpp | 3 ++- src/test/util/net.h | 1 + 9 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index d6fcaa841a6..11fd819a7b8 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -452,6 +452,7 @@ private: if (conn_type == "block-relay-only") return "block"; if (conn_type == "manual" || conn_type == "feeler") return conn_type; if (conn_type == "addr-fetch") return "addr"; + if (conn_type == "private-broadcast") return "priv"; return ""; } std::string FormatServices(const UniValue& services) @@ -703,6 +704,7 @@ public: " \"manual\" - peer we manually added using RPC addnode or the -addnode/-connect config options\n" " \"feeler\" - short-lived connection for testing addresses\n" " \"addr\" - address fetch; short-lived connection for requesting addresses\n" + " \"priv\" - private broadcast; short-lived connection for broadcasting our transactions\n" " net Network the peer connected through (\"ipv4\", \"ipv6\", \"onion\", \"i2p\", \"cjdns\", or \"npr\" (not publicly routable))\n" " serv Services offered by the peer\n" " \"n\" - NETWORK: peer can serve the full block chain\n" diff --git a/src/net.cpp b/src/net.cpp index 4abcf20d48d..8ed61b80ea6 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1876,6 +1876,7 @@ bool CConnman::AddConnection(const std::string& address, ConnectionType conn_typ switch (conn_type) { case ConnectionType::INBOUND: case ConnectionType::MANUAL: + case ConnectionType::PRIVATE_BROADCAST: return false; case ConnectionType::OUTBOUND_FULL_RELAY: max_connections = m_max_outbound_full_relay; @@ -2666,6 +2667,7 @@ void CConnman::ThreadOpenConnections(const std::vector connect, std // peers from addrman. case ConnectionType::ADDR_FETCH: case ConnectionType::FEELER: + case ConnectionType::PRIVATE_BROADCAST: break; case ConnectionType::MANUAL: case ConnectionType::OUTBOUND_FULL_RELAY: diff --git a/src/net.h b/src/net.h index 1f8f1771403..dcbab754518 100644 --- a/src/net.h +++ b/src/net.h @@ -775,6 +775,7 @@ public: case ConnectionType::MANUAL: case ConnectionType::ADDR_FETCH: case ConnectionType::FEELER: + case ConnectionType::PRIVATE_BROADCAST: return false; } // no default case, so the compiler can warn about missing cases @@ -796,6 +797,7 @@ public: case ConnectionType::FEELER: case ConnectionType::BLOCK_RELAY: case ConnectionType::ADDR_FETCH: + case ConnectionType::PRIVATE_BROADCAST: return false; case ConnectionType::OUTBOUND_FULL_RELAY: case ConnectionType::MANUAL: @@ -817,6 +819,11 @@ public: return m_conn_type == ConnectionType::ADDR_FETCH; } + bool IsPrivateBroadcastConn() const + { + return m_conn_type == ConnectionType::PRIVATE_BROADCAST; + } + bool IsInboundConn() const { return m_conn_type == ConnectionType::INBOUND; } @@ -830,6 +837,7 @@ public: case ConnectionType::OUTBOUND_FULL_RELAY: case ConnectionType::BLOCK_RELAY: case ConnectionType::ADDR_FETCH: + case ConnectionType::PRIVATE_BROADCAST: return true; } // no default case, so the compiler can warn about missing cases diff --git a/src/node/connection_types.cpp b/src/node/connection_types.cpp index 5e4dc5bf2ef..4cf98047cf1 100644 --- a/src/node/connection_types.cpp +++ b/src/node/connection_types.cpp @@ -20,6 +20,8 @@ std::string ConnectionTypeAsString(ConnectionType conn_type) return "block-relay-only"; case ConnectionType::ADDR_FETCH: return "addr-fetch"; + case ConnectionType::PRIVATE_BROADCAST: + return "private-broadcast"; } // no default case, so the compiler can warn about missing cases assert(false); diff --git a/src/node/connection_types.h b/src/node/connection_types.h index a00895e2a8a..eeb106b616d 100644 --- a/src/node/connection_types.h +++ b/src/node/connection_types.h @@ -75,6 +75,13 @@ enum class ConnectionType { * AddrMan is empty. */ ADDR_FETCH, + + /** + * Private broadcast connections are short-lived and only opened to + * privacy networks (Tor, I2P) for relaying privacy-sensitive data (like + * our own transactions) and closed afterwards. + */ + PRIVATE_BROADCAST, }; /** Convert ConnectionType enum to a string value */ diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 3aa4808878c..1619227a419 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -722,6 +722,8 @@ QString ConnectionTypeToQString(ConnectionType conn_type, bool prepend_direction case ConnectionType::FEELER: return prefix + QObject::tr("Feeler"); //: Short-lived peer connection type that solicits known addresses from a peer. case ConnectionType::ADDR_FETCH: return prefix + QObject::tr("Address Fetch"); + //: Short-lived peer connection type that is used for broadcasting privacy-sensitive data. + case ConnectionType::PRIVATE_BROADCAST: return prefix + QObject::tr("Private Broadcast"); } // no default case, so the compiler can warn about missing cases assert(false); } diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index d6d2be7b393..8723a52a087 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -484,7 +484,10 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty tr("Outbound Feeler: short-lived, for testing addresses"), /*: Explanatory text for a short-lived outbound peer connection that is used to request addresses from a peer. */ - tr("Outbound Address Fetch: short-lived, for soliciting addresses")}; + tr("Outbound Address Fetch: short-lived, for soliciting addresses"), + /*: Explanatory text for a short-lived outbound peer connection that is used + to broadcast privacy-sensitive data (like our transactions). */ + tr("Private broadcast: short-lived, for broadcasting privacy-sensitive transactions")}; const QString connection_types_list{""}; ui->peerConnectionTypeLabel->setToolTip(ui->peerConnectionTypeLabel->toolTip().arg(connection_types_list)); const std::vector TRANSPORT_TYPE_DOC{ diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index c97d4c75af0..e48ca1a5138 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -48,7 +48,8 @@ const std::vector CONNECTION_TYPE_DOC{ "inbound (initiated by the peer)", "manual (added via addnode RPC or -addnode/-connect configuration options)", "addr-fetch (short-lived automatic connection for soliciting addresses)", - "feeler (short-lived automatic connection for testing addresses)" + "feeler (short-lived automatic connection for testing addresses)", + "private-broadcast (short-lived automatic connection for broadcasting privacy-sensitive transactions)" }; const std::vector TRANSPORT_TYPE_DOC{ diff --git a/src/test/util/net.h b/src/test/util/net.h index 77954d92a48..605b2fa81a0 100644 --- a/src/test/util/net.h +++ b/src/test/util/net.h @@ -143,6 +143,7 @@ constexpr ConnectionType ALL_CONNECTION_TYPES[]{ ConnectionType::FEELER, ConnectionType::BLOCK_RELAY, ConnectionType::ADDR_FETCH, + ConnectionType::PRIVATE_BROADCAST, }; constexpr auto ALL_NETWORKS = std::array{