Skip to content

Commit

Permalink
Drop OMs from disconnected peers in OnionMessenger
Browse files Browse the repository at this point in the history
And refuse to forward OMs to disconnected peers
  • Loading branch information
valentinewallace committed Aug 4, 2022
1 parent a70e7a8 commit d93d568
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 11 deletions.
5 changes: 5 additions & 0 deletions lightning/src/ln/msgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,11 @@ pub trait RoutingMessageHandler : MessageSendEventsProvider {
pub trait OnionMessageHandler : OnionMessageProvider {
/// Handle an incoming onion_message message from the given peer.
fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage);
///
fn peer_connected(&self, their_node_id: &PublicKey, init: &Init);
/// Indicates a connection to the peer failed/an existing connection was lost. Allows handlers to
/// drop and refuse to forward onion messages to this peer.
fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool);
}

mod fuzzy_internal_msgs {
Expand Down
10 changes: 9 additions & 1 deletion lightning/src/ln/peer_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ impl OnionMessageProvider for IgnoringMessageHandler {
}
impl OnionMessageHandler for IgnoringMessageHandler {
fn handle_onion_message(&self, _their_node_id: &PublicKey, _msg: &msgs::OnionMessage) {}
fn peer_connected(&self, _their_node_id: &PublicKey, _init: &msgs::Init) {}
fn peer_disconnected(&self, _their_node_id: &PublicKey, _no_connection_possible: bool) {}
}
impl Deref for IgnoringMessageHandler {
type Target = IgnoringMessageHandler;
Expand Down Expand Up @@ -1154,8 +1156,9 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
}

self.message_handler.route_handler.peer_connected(&their_node_id, &msg);

self.message_handler.chan_handler.peer_connected(&their_node_id, &msg);
self.message_handler.onion_message_handler.peer_connected(&their_node_id, &msg);

peer_lock.their_features = Some(msg.features);
return Ok(None);
} else if peer_lock.their_features.is_none() {
Expand Down Expand Up @@ -1734,6 +1737,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
}
descriptor.disconnect_socket();
self.message_handler.chan_handler.peer_disconnected(&node_id, false);
self.message_handler.onion_message_handler.peer_disconnected(&node_id, false);
}
}
}
Expand Down Expand Up @@ -1761,6 +1765,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
log_pubkey!(node_id), if no_connection_possible { "no " } else { "" });
self.node_id_to_descriptor.lock().unwrap().remove(&node_id);
self.message_handler.chan_handler.peer_disconnected(&node_id, no_connection_possible);
self.message_handler.onion_message_handler.peer_disconnected(&node_id, no_connection_possible);
}
}
};
Expand All @@ -1781,6 +1786,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
log_trace!(self.logger, "Disconnecting peer with id {} due to client request", node_id);
peers_lock.remove(&descriptor);
self.message_handler.chan_handler.peer_disconnected(&node_id, no_connection_possible);
self.message_handler.onion_message_handler.peer_disconnected(&node_id, no_connection_possible);
descriptor.disconnect_socket();
}
}
Expand All @@ -1796,6 +1802,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
if let Some(node_id) = peer.lock().unwrap().their_node_id {
log_trace!(self.logger, "Disconnecting peer with id {} due to client request to disconnect all peers", node_id);
self.message_handler.chan_handler.peer_disconnected(&node_id, false);
self.message_handler.onion_message_handler.peer_disconnected(&node_id, false);
}
descriptor.disconnect_socket();
}
Expand Down Expand Up @@ -1886,6 +1893,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
log_trace!(self.logger, "Disconnecting peer with id {} due to ping timeout", node_id);
self.node_id_to_descriptor.lock().unwrap().remove(&node_id);
self.message_handler.chan_handler.peer_disconnected(&node_id, false);
self.message_handler.onion_message_handler.peer_disconnected(&node_id, false);
}
}
}
Expand Down
24 changes: 14 additions & 10 deletions lightning/src/onion_message/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@
//! Onion message testing and test utilities live here.
use chain::keysinterface::{KeysInterface, Recipient};
use ln::msgs::OnionMessageHandler;
use ln::features::InitFeatures;
use ln::msgs::{self, OnionMessageHandler};
use super::{BlindedRoute, Destination, OnionMessenger, SendError};
use util::enforcing_trait_impls::EnforcingSigner;
use util::events::MessageSendEvent;
use util::test_utils;

use bitcoin::network::constants::Network;
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
use bitcoin::secp256k1::{PublicKey, Secp256k1};

use sync::Arc;

Expand All @@ -35,18 +36,24 @@ impl MessengerNode {
}

fn create_nodes(num_messengers: u8) -> Vec<MessengerNode> {
let mut res = Vec::new();
let mut nodes = Vec::new();
for i in 0..num_messengers {
let logger = Arc::new(test_utils::TestLogger::with_id(format!("node {}", i)));
let seed = [i as u8; 32];
let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&seed, Network::Testnet));
res.push(MessengerNode {
nodes.push(MessengerNode {
keys_manager: keys_manager.clone(),
messenger: OnionMessenger::new(keys_manager, logger.clone()),
logger,
});
}
res
for idx in 0..num_messengers - 1 {
let i = idx as usize;
let init_msg = msgs::Init { features: InitFeatures::known(), remote_network_address: None };
nodes[i].messenger.peer_connected(&nodes[i + 1].get_node_pk(), &init_msg.clone());
nodes[i + 1].messenger.peer_connected(&nodes[i].get_node_pk(), &init_msg.clone());
}
nodes
}

fn pass_along_path(mut path: Vec<MessengerNode>, expected_path_id: Option<[u8; 32]>) {
Expand Down Expand Up @@ -114,12 +121,9 @@ fn three_blinded_hops() {
#[test]
fn too_big_packet_error() {
// Make sure we error as expected if a packet is too big to send.
let nodes = create_nodes(1);

let hop_secret = SecretKey::from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap();
let secp_ctx = Secp256k1::new();
let hop_node_id = PublicKey::from_secret_key(&secp_ctx, &hop_secret);
let nodes = create_nodes(2);

let hop_node_id = nodes[1].get_node_pk();
let hops = [hop_node_id; 400];
let err = nodes[0].messenger.send_onion_message(&hops, Destination::Node(hop_node_id)).unwrap_err();
assert_eq!(err, SendError::TooBigPacket);
Expand Down
37 changes: 37 additions & 0 deletions lightning/src/onion_message/messenger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ pub struct OnionMessenger<Signer: Sign, K: Deref, L: Deref>
keys_manager: K,
logger: L,
pending_messages: Mutex<HashMap<PublicKey, Vec<MessageSendEvent>>>,
peer_set: Mutex<HashSet<PublicKey>>,
secp_ctx: Secp256k1<secp256k1::All>,
// Coming soon:
// invoice_handler: InvoiceHandler,
Expand Down Expand Up @@ -121,6 +122,9 @@ pub enum SendError {
/// The provided [`Destination`] was an invalid [`BlindedRoute`], due to having fewer than two
/// blinded hops.
TooFewBlindedHops,
/// Our next-hop peer was offline or does not support onion message forwarding.
// See TODO in `peer_connected`
InvalidFirstHop,
}

impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
Expand All @@ -134,6 +138,7 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes());
OnionMessenger {
keys_manager,
peer_set: Mutex::new(HashSet::new()),
pending_messages: Mutex::new(HashMap::new()),
secp_ctx,
logger,
Expand All @@ -159,6 +164,9 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
(introduction_node_id, blinding_point),
}
};
if !self.peer_connected(&introduction_node_id) {
return Err(SendError::InvalidFirstHop)
}
let (packet_payloads, packet_keys) = packet_payloads_and_keys(
&self.secp_ctx, intermediate_nodes, destination, &blinding_secret)
.map_err(|e| SendError::Secp256k1(e))?;
Expand All @@ -179,6 +187,11 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
Ok(())
}

fn peer_connected(&self, peer_node_id: &PublicKey) -> bool {
let peers = self.peer_set.lock().unwrap();
peers.contains(peer_node_id)
}

#[cfg(test)]
pub(super) fn release_pending_msgs(&self) -> HashMap<PublicKey, Vec<MessageSendEvent>> {
let mut pending_msgs = self.pending_messages.lock().unwrap();
Expand Down Expand Up @@ -229,6 +242,10 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Si
Ok((Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs {
next_node_id, next_blinding_override
})), Some((next_hop_hmac, new_packet_bytes)))) => {
if !self.peer_connected(&next_node_id) {
log_trace!(self.logger, "Dropping onion message to disconnected peer {:?}", next_node_id);
return
}
// TODO: we need to check whether `next_node_id` is our node, in which case this is a dummy
// blinded hop and this onion message is destined for us. In this situation, we should keep
// unwrapping the onion layers to get to the final payload. Since we don't have the option
Expand Down Expand Up @@ -282,6 +299,26 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Si
},
};
}

fn peer_connected(&self, their_node_id: &PublicKey, _init: &msgs::Init) {
// TODO: check feature bits to see if onion message forwarding is supported
let mut peers = self.peer_set.lock().unwrap();
peers.insert(their_node_id.clone());
}

fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool) {
{
let mut peers = self.peer_set.lock().unwrap();
peers.remove(their_node_id);
}

let mut pending_msgs = self.pending_messages.lock().unwrap();
if no_connection_possible {
pending_msgs.remove(their_node_id);
} else if let Some(msgs) = pending_msgs.get_mut(their_node_id) {
msgs.clear();
}
}
}

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

0 comments on commit d93d568

Please sign in to comment.