From f8906d71e0b898a23807212b5a422e838beaad9c Mon Sep 17 00:00:00 2001 From: Leo Nash Date: Mon, 2 Feb 2026 18:04:48 +0000 Subject: [PATCH] Add `remote_addr` field to `lightning_net_tokio::setup_outbound` When `setup_outbound` was used to setup a connection proxied over Tor, it previously set `remote_addr` to the address of the Tor proxy, and not the address of the peer on the other side of the stream. The address of the Tor proxy was assigned to the `PeerDetails::socket_address` for that peer in `PeerManager::list_peers`, and if it was not a private IPV4 or IPV6 address, it was also reported to the peer in our init message. Here we ask callers of `setup_outbound` to pass a `remote_addr` separately from the `StdTcpStream`. `connect_outbound` sets this new `remote_addr` parameter to `get_addr_from_stream`, and `tor_connect_outbound` passes its own `addr` parameter directly to `remote_addr`. Notably, Onion V3 addresses will now appear in `PeerManager::list_peers` for outbound Tor connections to Onion V3 services made using `tor_connect_outbound`, and will be reported to the peer in our init message. While this adds a new parameter to the public `fn setup_outbound` function, this closely mirrors the existing public method `PeerManager::new_outbound_connection`. --- lightning-net-tokio/src/lib.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/lightning-net-tokio/src/lib.rs b/lightning-net-tokio/src/lib.rs index eec0e424eaa..47deaf62e25 100644 --- a/lightning-net-tokio/src/lib.rs +++ b/lightning-net-tokio/src/lib.rs @@ -374,16 +374,24 @@ where /// making an outbound connection which is expected to be accepted by a peer with the given /// public key. The relevant processing is set to run free (via tokio::spawn). /// +/// The `remote_addr` parameter should be set to the remote network address the stream is +/// connected to, and will set the [`PeerDetails::socket_address`] field for that peer in +/// [`PeerManager::list_peers`]. If this address is set, and it is not a private IPV4 or IPV6 +/// address, it will also be reported to the peer in our init message. +/// /// The returned future will complete when the peer is disconnected and associated handling /// futures are freed, though, because all processing futures are spawned with tokio::spawn, you do /// not need to poll the provided future in order to make progress. +/// +/// [`PeerDetails::socket_address`]: lightning::ln::peer_handler::PeerDetails::socket_address +/// [`PeerManager::list_peers`]: lightning::ln::peer_handler::PeerManager::list_peers pub fn setup_outbound( peer_manager: PM, their_node_id: PublicKey, stream: StdTcpStream, + remote_addr: Option, ) -> impl std::future::Future where PM::Target: APeerManager, { - let remote_addr = get_addr_from_stream(&stream); let (reader, mut write_receiver, read_receiver, us) = Connection::new(stream); #[cfg(test)] let last_us = Arc::clone(&us); @@ -469,7 +477,8 @@ where if let Ok(Ok(stream)) = time::timeout(Duration::from_secs(CONNECT_OUTBOUND_TIMEOUT), connect_fut).await { - Some(setup_outbound(peer_manager, their_node_id, stream)) + let remote_addr = get_addr_from_stream(&stream); + Some(setup_outbound(peer_manager, their_node_id, stream, remote_addr)) } else { None } @@ -488,12 +497,14 @@ where PM::Target: APeerManager, { let connect_fut = async { - tor_connect(addr, tor_proxy_addr, entropy_source).await.map(|s| s.into_std().unwrap()) + tor_connect(addr.clone(), tor_proxy_addr, entropy_source) + .await + .map(|s| s.into_std().unwrap()) }; if let Ok(Ok(stream)) = time::timeout(Duration::from_secs(TOR_CONNECT_OUTBOUND_TIMEOUT), connect_fut).await { - Some(setup_outbound(peer_manager, their_node_id, stream)) + Some(setup_outbound(peer_manager, their_node_id, stream, Some(addr))) } else { None } @@ -1015,7 +1026,8 @@ mod tests { // 127.0.0.1. let (conn_a, conn_b) = make_tcp_connection(); - let fut_a = super::setup_outbound(Arc::clone(&a_manager), b_pub, conn_a); + let remote_addr = super::get_addr_from_stream(&conn_a); + let fut_a = super::setup_outbound(Arc::clone(&a_manager), b_pub, conn_a, remote_addr); let fut_b = super::setup_inbound(b_manager, conn_b); tokio::time::timeout(Duration::from_secs(10), a_connected.recv()).await.unwrap(); @@ -1085,7 +1097,10 @@ mod tests { // Call connection setup inside new tokio tasks. let manager_reference = Arc::clone(&a_manager); tokio::spawn(async move { super::setup_inbound(manager_reference, conn_a).await }); - tokio::spawn(async move { super::setup_outbound(a_manager, b_pub, conn_b).await }); + let remote_addr = super::get_addr_from_stream(&conn_b); + tokio::spawn( + async move { super::setup_outbound(a_manager, b_pub, conn_b, remote_addr).await }, + ); } #[tokio::test(flavor = "multi_thread")]