Skip to content

Commit 030955d

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 f49e04d commit 030955d

File tree

5 files changed

+96
-47
lines changed

5 files changed

+96
-47
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, NodeContext],
439+
"Feature flags for `option_onion_messages`.", 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: 59 additions & 34 deletions
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>
@@ -163,25 +165,29 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
163165
.map_err(|e| SendError::Secp256k1(e))?;
164166

165167
let prng_seed = self.keys_manager.get_secure_random_bytes();
166-
let onion_packet = construct_onion_message_packet(
168+
let onion_routing_packet = construct_onion_message_packet(
167169
packet_payloads, packet_keys, prng_seed).map_err(|()| SendError::TooBigPacket)?;
168170

169171
let mut pending_per_peer_msgs = self.pending_messages.lock().unwrap();
170-
let pending_msgs = pending_per_peer_msgs.entry(introduction_node_id).or_insert_with(VecDeque::new);
171-
pending_msgs.push_back(
172-
msgs::OnionMessage {
173-
blinding_point,
174-
onion_routing_packet: onion_packet,
172+
match pending_per_peer_msgs.entry(introduction_node_id) {
173+
hash_map::Entry::Vacant(_) => Err(SendError::InvalidFirstHop),
174+
hash_map::Entry::Occupied(mut e) => {
175+
e.get_mut().push_back(msgs::OnionMessage { blinding_point, onion_routing_packet });
176+
Ok(())
175177
}
176-
);
177-
Ok(())
178+
}
178179
}
179180

180181
#[cfg(test)]
181182
pub(super) fn release_pending_msgs(&self) -> HashMap<PublicKey, VecDeque<msgs::OnionMessage>> {
182183
let mut pending_msgs = self.pending_messages.lock().unwrap();
183184
let mut msgs = HashMap::new();
184-
core::mem::swap(&mut *pending_msgs, &mut msgs);
185+
// We don't want to disconnect the peers by removing them entirely from the original map, so we
186+
// swap the pending message buffers individually.
187+
for (peer_node_id, pending_messages) in &mut *pending_msgs {
188+
msgs.insert(*peer_node_id, VecDeque::new());
189+
core::mem::swap(pending_messages, msgs.get_mut(&peer_node_id).unwrap());
190+
}
185191
msgs
186192
}
187193
}
@@ -250,32 +256,39 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Si
250256
};
251257

252258
let mut pending_per_peer_msgs = self.pending_messages.lock().unwrap();
253-
let pending_msgs = pending_per_peer_msgs.entry(next_node_id).or_insert_with(VecDeque::new);
254-
pending_msgs.push_back(
255-
msgs::OnionMessage {
256-
blinding_point: match next_blinding_override {
257-
Some(blinding_point) => blinding_point,
258-
None => {
259-
let blinding_factor = {
260-
let mut sha = Sha256::engine();
261-
sha.input(&msg.blinding_point.serialize()[..]);
262-
sha.input(control_tlvs_ss.as_ref());
263-
Sha256::from_engine(sha).into_inner()
264-
};
265-
let next_blinding_point = msg.blinding_point;
266-
match next_blinding_point.mul_tweak(&self.secp_ctx, &Scalar::from_be_bytes(blinding_factor).unwrap()) {
267-
Ok(bp) => bp,
268-
Err(e) => {
269-
log_trace!(self.logger, "Failed to compute next blinding point: {}", e);
270-
return
271-
}
272-
}
273-
},
274-
},
275-
onion_routing_packet: outgoing_packet,
259+
match pending_per_peer_msgs.entry(next_node_id) {
260+
hash_map::Entry::Vacant(_) => {
261+
log_trace!(self.logger, "Dropping forwarded onion message to disconnected peer {:?}", next_node_id);
262+
return
276263
},
277-
);
278-
log_trace!(self.logger, "Forwarding an onion message to peer {}", next_node_id);
264+
hash_map::Entry::Occupied(mut e) => {
265+
e.get_mut().push_back(
266+
msgs::OnionMessage {
267+
blinding_point: match next_blinding_override {
268+
Some(blinding_point) => blinding_point,
269+
None => {
270+
let blinding_factor = {
271+
let mut sha = Sha256::engine();
272+
sha.input(&msg.blinding_point.serialize()[..]);
273+
sha.input(control_tlvs_ss.as_ref());
274+
Sha256::from_engine(sha).into_inner()
275+
};
276+
let next_blinding_point = msg.blinding_point;
277+
match next_blinding_point.mul_tweak(&self.secp_ctx, &Scalar::from_be_bytes(blinding_factor).unwrap()) {
278+
Ok(bp) => bp,
279+
Err(e) => {
280+
log_trace!(self.logger, "Failed to compute next blinding point: {}", e);
281+
return
282+
}
283+
}
284+
},
285+
},
286+
onion_routing_packet: outgoing_packet,
287+
},
288+
);
289+
log_trace!(self.logger, "Forwarding an onion message to peer {}", next_node_id);
290+
}
291+
};
279292
},
280293
Err(e) => {
281294
log_trace!(self.logger, "Errored decoding onion message packet: {:?}", e);
@@ -285,6 +298,18 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Si
285298
},
286299
};
287300
}
301+
302+
fn peer_connected(&self, their_node_id: &PublicKey, init: &msgs::Init) {
303+
if init.features.supports_onion_messages() {
304+
let mut peers = self.pending_messages.lock().unwrap();
305+
peers.insert(their_node_id.clone(), VecDeque::new());
306+
}
307+
}
308+
309+
fn peer_disconnected(&self, their_node_id: &PublicKey, _no_connection_possible: bool) {
310+
let mut pending_msgs = self.pending_messages.lock().unwrap();
311+
pending_msgs.remove(their_node_id);
312+
}
288313
}
289314

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

0 commit comments

Comments
 (0)