Skip to content

Commit ee37e44

Browse files
Refuse to send and forward OMs to disconnected peers
We also refuse to connect to peers that don't advertise onion message forwarding support.
1 parent 0efc407 commit ee37e44

File tree

5 files changed

+72
-14
lines changed

5 files changed

+72
-14
lines changed

lightning/src/ln/features.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,11 @@ mod sealed {
433433
define_feature!(27, ShutdownAnySegwit, [InitContext, NodeContext],
434434
"Feature flags for `opt_shutdown_anysegwit`.", set_shutdown_any_segwit_optional,
435435
set_shutdown_any_segwit_required, supports_shutdown_anysegwit, requires_shutdown_anysegwit);
436+
// We do not yet advertise the onion messages feature bit, but we need to detect when peers
437+
// support it.
438+
define_feature!(39, OnionMessages, [InitContext],
439+
"Feature flags for onion message forwarding.", set_onion_messages_optional,
440+
set_onion_messages_required, supports_onion_messages, requires_onion_messages);
436441
define_feature!(45, ChannelType, [InitContext, NodeContext],
437442
"Feature flags for `option_channel_type`.", set_channel_type_optional,
438443
set_channel_type_required, supports_channel_type, requires_channel_type);
@@ -767,7 +772,7 @@ impl<T: sealed::GossipQueries> Features<T> {
767772

768773
impl<T: sealed::InitialRoutingSync> Features<T> {
769774
// We are no longer setting initial_routing_sync now that gossip_queries
770-
// is enabled. This feature is ignored by a peer when gossip_queries has
775+
// is enabled. This feature is ignored by a peer when gossip_queries has
771776
// been negotiated.
772777
#[cfg(test)]
773778
pub(crate) fn clear_initial_routing_sync(&mut self) {

lightning/src/ln/msgs.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,12 @@ pub trait RoutingMessageHandler : MessageSendEventsProvider {
949949
pub trait OnionMessageHandler : OnionMessageProvider {
950950
/// Handle an incoming onion_message message from the given peer.
951951
fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage);
952+
/// Called when a connection is established with a peer. Can be used to track which peers
953+
/// advertise onion message support and are online.
954+
fn peer_connected(&self, their_node_id: &PublicKey, init: &Init);
955+
/// Indicates a connection to the peer failed/an existing connection was lost. Allows handlers to
956+
/// drop and refuse to forward onion messages to this peer.
957+
fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool);
952958
}
953959

954960
mod fuzzy_internal_msgs {

lightning/src/ln/peer_handler.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ impl OnionMessageProvider for IgnoringMessageHandler {
8181
}
8282
impl OnionMessageHandler for IgnoringMessageHandler {
8383
fn handle_onion_message(&self, _their_node_id: &PublicKey, _msg: &msgs::OnionMessage) {}
84+
fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init) {}
85+
fn peer_disconnected(&self, _their_node_id: &PublicKey, _no_connection_possible: bool) {}
8486
}
8587
impl Deref for IgnoringMessageHandler {
8688
type Target = IgnoringMessageHandler;
@@ -1173,8 +1175,9 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
11731175
}
11741176

11751177
self.message_handler.route_handler.peer_connected(&their_node_id, &msg);
1176-
11771178
self.message_handler.chan_handler.peer_connected(&their_node_id, &msg);
1179+
self.message_handler.onion_message_handler.peer_connected(&their_node_id, &msg);
1180+
11781181
peer_lock.their_features = Some(msg.features);
11791182
return Ok(None);
11801183
} else if peer_lock.their_features.is_none() {
@@ -1729,6 +1732,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
17291732
}
17301733
descriptor.disconnect_socket();
17311734
self.message_handler.chan_handler.peer_disconnected(&node_id, false);
1735+
self.message_handler.onion_message_handler.peer_disconnected(&node_id, false);
17321736
}
17331737
}
17341738
}
@@ -1756,6 +1760,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
17561760
log_pubkey!(node_id), if no_connection_possible { "no " } else { "" });
17571761
self.node_id_to_descriptor.lock().unwrap().remove(&node_id);
17581762
self.message_handler.chan_handler.peer_disconnected(&node_id, no_connection_possible);
1763+
self.message_handler.onion_message_handler.peer_disconnected(&node_id, no_connection_possible);
17591764
}
17601765
}
17611766
};
@@ -1776,6 +1781,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
17761781
log_trace!(self.logger, "Disconnecting peer with id {} due to client request", node_id);
17771782
peers_lock.remove(&descriptor);
17781783
self.message_handler.chan_handler.peer_disconnected(&node_id, no_connection_possible);
1784+
self.message_handler.onion_message_handler.peer_disconnected(&node_id, no_connection_possible);
17791785
descriptor.disconnect_socket();
17801786
}
17811787
}
@@ -1791,6 +1797,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
17911797
if let Some(node_id) = peer.lock().unwrap().their_node_id {
17921798
log_trace!(self.logger, "Disconnecting peer with id {} due to client request to disconnect all peers", node_id);
17931799
self.message_handler.chan_handler.peer_disconnected(&node_id, false);
1800+
self.message_handler.onion_message_handler.peer_disconnected(&node_id, false);
17941801
}
17951802
descriptor.disconnect_socket();
17961803
}
@@ -1881,6 +1888,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
18811888
log_trace!(self.logger, "Disconnecting peer with id {} due to ping timeout", node_id);
18821889
self.node_id_to_descriptor.lock().unwrap().remove(&node_id);
18831890
self.message_handler.chan_handler.peer_disconnected(&node_id, false);
1891+
self.message_handler.onion_message_handler.peer_disconnected(&node_id, false);
18841892
}
18851893
}
18861894
}

lightning/src/onion_message/functional_tests.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@
1010
//! Onion message testing and test utilities live here.
1111
1212
use chain::keysinterface::{KeysInterface, Recipient};
13-
use ln::msgs::OnionMessageHandler;
13+
use ln::features::InitFeatures;
14+
use ln::msgs::{self, OnionMessageHandler};
1415
use super::{BlindedRoute, Destination, OnionMessenger, SendError};
1516
use util::enforcing_trait_impls::EnforcingSigner;
1617
use util::test_utils;
1718

1819
use bitcoin::network::constants::Network;
19-
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
20+
use bitcoin::secp256k1::{PublicKey, Secp256k1};
2021

2122
use sync::Arc;
2223

@@ -34,26 +35,33 @@ impl MessengerNode {
3435
}
3536

3637
fn create_nodes(num_messengers: u8) -> Vec<MessengerNode> {
37-
let mut res = Vec::new();
38+
let mut nodes = Vec::new();
3839
for i in 0..num_messengers {
3940
let logger = Arc::new(test_utils::TestLogger::with_id(format!("node {}", i)));
4041
let seed = [i as u8; 32];
4142
let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&seed, Network::Testnet));
42-
res.push(MessengerNode {
43+
nodes.push(MessengerNode {
4344
keys_manager: keys_manager.clone(),
4445
messenger: OnionMessenger::new(keys_manager, logger.clone()),
4546
logger,
4647
});
4748
}
48-
res
49+
for idx in 0..num_messengers - 1 {
50+
let i = idx as usize;
51+
let mut features = InitFeatures::known();
52+
features.set_onion_messages_optional();
53+
let init_msg = msgs::Init { features, remote_network_address: None };
54+
nodes[i].messenger.peer_connected(&nodes[i + 1].get_node_pk(), &init_msg.clone());
55+
nodes[i + 1].messenger.peer_connected(&nodes[i].get_node_pk(), &init_msg.clone());
56+
}
57+
nodes
4958
}
5059

5160
fn pass_along_path(path: &Vec<MessengerNode>, expected_path_id: Option<[u8; 32]>) {
5261
let mut prev_node = &path[0];
5362
let num_nodes = path.len();
5463
for (idx, node) in path.into_iter().skip(1).enumerate() {
5564
let events = prev_node.messenger.release_pending_msgs();
56-
assert_eq!(events.len(), 1);
5765
let onion_msg = {
5866
let msgs = events.get(&node.get_node_pk()).unwrap();
5967
assert_eq!(msgs.len(), 1);
@@ -110,12 +118,9 @@ fn three_blinded_hops() {
110118
#[test]
111119
fn too_big_packet_error() {
112120
// Make sure we error as expected if a packet is too big to send.
113-
let nodes = create_nodes(1);
114-
115-
let hop_secret = SecretKey::from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap();
116-
let secp_ctx = Secp256k1::new();
117-
let hop_node_id = PublicKey::from_secret_key(&secp_ctx, &hop_secret);
121+
let nodes = create_nodes(2);
118122

123+
let hop_node_id = nodes[1].get_node_pk();
119124
let hops = [hop_node_id; 400];
120125
let err = nodes[0].messenger.send_onion_message(&hops, Destination::Node(hop_node_id), None).unwrap_err();
121126
assert_eq!(err, SendError::TooBigPacket);

lightning/src/onion_message/messenger.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ pub enum SendError {
120120
/// The provided [`Destination`] was an invalid [`BlindedRoute`], due to having fewer than two
121121
/// blinded hops.
122122
TooFewBlindedHops,
123+
/// Our next-hop peer was offline or does not support onion message forwarding.
124+
InvalidFirstHop,
123125
}
124126

125127
impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
@@ -158,6 +160,9 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
158160
(introduction_node_id, blinding_point),
159161
}
160162
};
163+
if !self.peer_connected(&introduction_node_id) {
164+
return Err(SendError::InvalidFirstHop)
165+
}
161166
let (packet_payloads, packet_keys) = packet_payloads_and_keys(
162167
&self.secp_ctx, intermediate_nodes, destination, reply_path, &blinding_secret)
163168
.map_err(|e| SendError::Secp256k1(e))?;
@@ -177,11 +182,20 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
177182
Ok(())
178183
}
179184

185+
fn peer_connected(&self, peer_node_id: &PublicKey) -> bool {
186+
self.pending_messages.lock().unwrap().contains_key(peer_node_id)
187+
}
188+
180189
#[cfg(test)]
181190
pub(super) fn release_pending_msgs(&self) -> HashMap<PublicKey, VecDeque<msgs::OnionMessage>> {
182191
let mut pending_msgs = self.pending_messages.lock().unwrap();
183192
let mut msgs = HashMap::new();
184-
core::mem::swap(&mut *pending_msgs, &mut msgs);
193+
// We don't want to disconnect the peers by removing them entirely from the original map, so we
194+
// swap the pending message buffers individually.
195+
for (peer_node_id, pending_messages) in &mut *pending_msgs {
196+
msgs.insert(*peer_node_id, VecDeque::new());
197+
core::mem::swap(pending_messages, msgs.get_mut(&peer_node_id).unwrap());
198+
}
185199
msgs
186200
}
187201
}
@@ -230,6 +244,10 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Si
230244
Ok((Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs {
231245
next_node_id, next_blinding_override
232246
})), Some((next_hop_hmac, new_packet_bytes)))) => {
247+
if !self.peer_connected(&next_node_id) {
248+
log_trace!(self.logger, "Dropping onion message to disconnected peer {:?}", next_node_id);
249+
return
250+
}
233251
// TODO: we need to check whether `next_node_id` is our node, in which case this is a dummy
234252
// blinded hop and this onion message is destined for us. In this situation, we should keep
235253
// unwrapping the onion layers to get to the final payload. Since we don't have the option
@@ -285,6 +303,22 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Si
285303
},
286304
};
287305
}
306+
307+
fn peer_connected(&self, their_node_id: &PublicKey, init: &msgs::Init) {
308+
if init.features.supports_onion_messages() {
309+
let mut peers = self.pending_messages.lock().unwrap();
310+
peers.insert(their_node_id.clone(), VecDeque::new());
311+
}
312+
}
313+
314+
fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool) {
315+
let mut pending_msgs = self.pending_messages.lock().unwrap();
316+
if no_connection_possible {
317+
pending_msgs.remove(their_node_id);
318+
} else if let Some(msgs) = pending_msgs.get_mut(their_node_id) {
319+
msgs.clear();
320+
}
321+
}
288322
}
289323

290324
impl<Signer: Sign, K: Deref, L: Deref> OnionMessageProvider for OnionMessenger<Signer, K, L>

0 commit comments

Comments
 (0)