From e8f7fe1919f43de9c7da88f8fbe1854d9e88c7e4 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Thu, 21 Mar 2024 13:56:54 -0400 Subject: [PATCH 1/9] Support generating events when an OM for an offline peer is received. Docs will be added in upcoming commits. --- lightning/src/events/mod.rs | 31 +++++++++++++++++++ lightning/src/onion_message/messenger.rs | 38 ++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index f6e7f716487..0fe1ae58348 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -1041,6 +1041,18 @@ pub enum Event { /// /// [`ChannelHandshakeConfig::negotiate_anchors_zero_fee_htlc_tx`]: crate::util::config::ChannelHandshakeConfig::negotiate_anchors_zero_fee_htlc_tx BumpTransaction(BumpTransactionEvent), + /// We received an onion message that is intended to be forwarded to a peer + /// that is currently offline. This event will only be generated if the + /// `OnionMessenger` was initialized with + /// [`OnionMessenger::new_with_offline_peer_interception`], see its docs. + /// + /// [`OnionMessenger::new_with_offline_peer_interception`]: crate::onion_message::messenger::OnionMessenger::new_with_offline_peer_interception + OnionMessageIntercepted { + /// The node id of the offline peer. + peer_node_id: PublicKey, + /// The onion message intended to be forwarded to `peer_node_id`. + message: msgs::OnionMessage, + }, } impl Writeable for Event { @@ -1286,6 +1298,13 @@ impl Writeable for Event { 35u8.write(writer)?; // Never write ConnectionNeeded events as buffered onion messages aren't serialized. }, + &Event::OnionMessageIntercepted { ref peer_node_id, ref message } => { + 37u8.write(writer)?; + write_tlv_fields!(writer, { + (0, peer_node_id, required), + (2, message, required), + }); + } // Note that, going forward, all new events must only write data inside of // `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write // data via `write_tlv_fields`. @@ -1697,6 +1716,18 @@ impl MaybeReadable for Event { }, // Note that we do not write a length-prefixed TLV for ConnectionNeeded events. 35u8 => Ok(None), + 37u8 => { + let mut f = || { + _init_and_read_len_prefixed_tlv_fields!(reader, { + (0, peer_node_id, required), + (2, message, required), + }); + Ok(Some(Event::OnionMessageIntercepted { + peer_node_id: peer_node_id.0.unwrap(), message: message.0.unwrap() + })) + }; + f() + }, // Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue. // Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt // reads. diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index 1d7a730fa36..87faef9288d 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -175,6 +175,8 @@ where message_router: MR, offers_handler: OMH, custom_handler: CMH, + intercept_messages_for_offline_peers: bool, + pending_events: Mutex>, } /// [`OnionMessage`]s buffered to be sent. @@ -796,6 +798,28 @@ where pub fn new( entropy_source: ES, node_signer: NS, logger: L, node_id_lookup: NL, message_router: MR, offers_handler: OMH, custom_handler: CMH + ) -> Self { + Self::new_inner( + entropy_source, node_signer, logger, node_id_lookup, message_router, + offers_handler, custom_handler, false + ) + } + + /// + pub fn new_with_offline_peer_interception( + entropy_source: ES, node_signer: NS, logger: L, node_id_lookup: NL, + message_router: MR, offers_handler: OMH, custom_handler: CMH + ) -> Self { + Self::new_inner( + entropy_source, node_signer, logger, node_id_lookup, message_router, + offers_handler, custom_handler, true + ) + } + + fn new_inner( + entropy_source: ES, node_signer: NS, logger: L, node_id_lookup: NL, + message_router: MR, offers_handler: OMH, custom_handler: CMH, + intercept_messages_for_offline_peers: bool ) -> Self { let mut secp_ctx = Secp256k1::new(); secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes()); @@ -809,6 +833,8 @@ where message_router, offers_handler, custom_handler, + intercept_messages_for_offline_peers, + pending_events: Mutex::new(Vec::new()), } } @@ -1004,6 +1030,11 @@ where } } } + let mut events = Vec::new(); + core::mem::swap(&mut *self.pending_events.lock().unwrap(), &mut events); + for ev in events { + handler.handle_event(ev); + } } } @@ -1081,6 +1112,13 @@ where e.get_mut().enqueue_message(onion_message); log_trace!(logger, "Forwarding an onion message to peer {}", next_node_id); }, + _ if self.intercept_messages_for_offline_peers => { + self.pending_events.lock().unwrap().push( + Event::OnionMessageIntercepted { + peer_node_id: next_node_id, message: onion_message + } + ); + }, _ => { log_trace!( logger, From 1c28cc071300005d9766fca3a402246973a811a5 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Fri, 22 Mar 2024 15:58:33 -0400 Subject: [PATCH 2/9] OnionMessenger: support generating peer connection events. Useful if we are in the mode of interception OMs for offline peers, so users know when to re-inject intercepted OMs. --- lightning/src/events/mod.rs | 29 ++++++++++++++++++++++++ lightning/src/onion_message/messenger.rs | 5 ++++ 2 files changed, 34 insertions(+) diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index 0fe1ae58348..09c52bd2a3f 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -1053,6 +1053,18 @@ pub enum Event { /// The onion message intended to be forwarded to `peer_node_id`. message: msgs::OnionMessage, }, + /// Indicates that an onion message supporting peer has come online and it may + /// be time to forward any onion messages that were previously intercepted for + /// them. This event will only be generated if the `OnionMessenger` was + /// initialized with + /// [`OnionMessenger::new_with_offline_peer_interception`], see its docs. + /// + /// [`OnionMessenger::new_with_offline_peer_interception`]: crate::onion_message::messenger::OnionMessenger::new_with_offline_peer_interception + OnionMessagePeerConnected { + /// The node id of the peer we just connected to, who advertises support for + /// onion messages. + peer_node_id: PublicKey, + } } impl Writeable for Event { @@ -1304,6 +1316,12 @@ impl Writeable for Event { (0, peer_node_id, required), (2, message, required), }); + }, + &Event::OnionMessagePeerConnected { ref peer_node_id } => { + 39u8.write(writer)?; + write_tlv_fields!(writer, { + (0, peer_node_id, required), + }); } // Note that, going forward, all new events must only write data inside of // `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write @@ -1728,6 +1746,17 @@ impl MaybeReadable for Event { }; f() }, + 39u8 => { + let mut f = || { + _init_and_read_len_prefixed_tlv_fields!(reader, { + (0, peer_node_id, required), + }); + Ok(Some(Event::OnionMessagePeerConnected { + peer_node_id: peer_node_id.0.unwrap() + })) + }; + f() + }, // Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue. // Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt // reads. diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index 87faef9288d..d956b392a39 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -1140,6 +1140,11 @@ where .entry(*their_node_id) .or_insert_with(|| OnionMessageRecipient::ConnectedPeer(VecDeque::new())) .mark_connected(); + if self.intercept_messages_for_offline_peers { + self.pending_events.lock().unwrap().push( + Event::OnionMessagePeerConnected { peer_node_id: *their_node_id } + ); + } } else { self.message_recipients.lock().unwrap().remove(their_node_id); } From 7213458b824cfa7f4ab95df2df1331e979d0e544 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Mon, 25 Mar 2024 11:42:13 -0400 Subject: [PATCH 3/9] Support forwarding prebuilt onion messages in OnionMessenger. --- lightning/src/onion_message/messenger.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index d956b392a39..213ac7fc9e7 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -943,6 +943,27 @@ where } } + /// Forwards an [`OnionMessage`] to `peer_node_id`. Useful if we initialized + /// the [`OnionMessenger`] with [`Self::new_with_offline_peer_interception`] + /// and want to forward a previously intercepted onion message to a peer that + /// has just come online. + pub fn forward_onion_message( + &self, message: OnionMessage, peer_node_id: &PublicKey + ) -> Result<(), SendError> { + let mut message_recipients = self.message_recipients.lock().unwrap(); + if outbound_buffer_full(&peer_node_id, &message_recipients) { + return Err(SendError::BufferFull); + } + + match message_recipients.entry(*peer_node_id) { + hash_map::Entry::Occupied(mut e) if e.get().is_connected() => { + e.get_mut().enqueue_message(message); + Ok(()) + }, + _ => Err(SendError::InvalidFirstHop(*peer_node_id)) + } + } + #[cfg(any(test, feature = "_test_utils"))] pub fn send_onion_message_using_path( &self, path: OnionMessagePath, contents: T, reply_path: Option From 1fc8f115af52bb2ba53fe37df955261d27578ba3 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Mon, 25 Mar 2024 13:14:29 -0400 Subject: [PATCH 4/9] Refactor MessengerNode test util construction to take config. Will be used in the next commit when another config parameter is added. --- .../src/onion_message/functional_tests.rs | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/lightning/src/onion_message/functional_tests.rs b/lightning/src/onion_message/functional_tests.rs index acf34a3a8c8..f0ca2eec735 100644 --- a/lightning/src/onion_message/functional_tests.rs +++ b/lightning/src/onion_message/functional_tests.rs @@ -155,14 +155,27 @@ impl CustomOnionMessageHandler for TestCustomMessageHandler { } fn create_nodes(num_messengers: u8) -> Vec { - let secrets = (1..=num_messengers) + let cfgs = (1..=num_messengers) .into_iter() - .map(|i| SecretKey::from_slice(&[i; 32]).unwrap()) + .map(|_| MessengerCfg::new()) .collect(); - create_nodes_using_secrets(secrets) + create_nodes_using_cfgs(cfgs) } -fn create_nodes_using_secrets(secrets: Vec) -> Vec { +struct MessengerCfg { + secret_override: Option, +} +impl MessengerCfg { + fn new() -> Self { + Self { secret_override: None } + } + fn with_node_secret(mut self, secret: SecretKey) -> Self { + self.secret_override = Some(secret); + self + } +} + +fn create_nodes_using_cfgs(cfgs: Vec) -> Vec { let gossip_logger = Arc::new(test_utils::TestLogger::with_id("gossip".to_string())); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, gossip_logger.clone())); let gossip_sync = Arc::new( @@ -170,7 +183,8 @@ fn create_nodes_using_secrets(secrets: Vec) -> Vec { ); let mut nodes = Vec::new(); - for (i, secret_key) in secrets.into_iter().enumerate() { + for (i, cfg) in cfgs.into_iter().enumerate() { + let secret_key = cfg.secret_override.unwrap_or(SecretKey::from_slice(&[(i + 1) as u8; 32]).unwrap()); let logger = Arc::new(test_utils::TestLogger::with_id(format!("node {}", i))); let seed = [i as u8; 32]; let entropy_source = Arc::new(test_utils::TestKeysInterface::new(&seed, Network::Testnet)); @@ -541,16 +555,17 @@ fn drops_buffered_messages_waiting_for_peer_connection() { #[test] fn spec_test_vector() { - let secret_keys = [ + let node_cfgs = [ "4141414141414141414141414141414141414141414141414141414141414141", // Alice "4242424242424242424242424242424242424242424242424242424242424242", // Bob "4343434343434343434343434343434343434343434343434343434343434343", // Carol "4444444444444444444444444444444444444444444444444444444444444444", // Dave ] .iter() - .map(|secret| SecretKey::from_slice(&>::from_hex(secret).unwrap()).unwrap()) + .map(|secret_hex| SecretKey::from_slice(&>::from_hex(secret_hex).unwrap()).unwrap()) + .map(|secret| MessengerCfg::new().with_node_secret(secret)) .collect(); - let nodes = create_nodes_using_secrets(secret_keys); + let nodes = create_nodes_using_cfgs(node_cfgs); // Hardcode the sender->Alice onion message, because it includes an unknown TLV of type 1, which // LDK doesn't support constructing. From 4c7ecaaa3fb25e16306cfe30141cba8e69ec5c6f Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Mon, 25 Mar 2024 13:23:00 -0400 Subject: [PATCH 5/9] Fix outdated comment in onion message functional test. --- lightning/src/onion_message/functional_tests.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lightning/src/onion_message/functional_tests.rs b/lightning/src/onion_message/functional_tests.rs index f0ca2eec735..41878ed1b9c 100644 --- a/lightning/src/onion_message/functional_tests.rs +++ b/lightning/src/onion_message/functional_tests.rs @@ -376,11 +376,10 @@ fn we_are_intro_node() { #[test] fn invalid_blinded_path_error() { - // Make sure we error as expected if a provided blinded path has 0 or 1 hops. + // Make sure we error as expected if a provided blinded path has 0 hops. let nodes = create_nodes(3); let test_msg = TestCustomMessage::Response; - // 0 hops let secp_ctx = Secp256k1::new(); let mut blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id, nodes[2].node_id], &*nodes[2].entropy_source, &secp_ctx).unwrap(); blinded_path.blinded_hops.clear(); From be31e632c2cb89dc94db7f6b5859213c8e04febd Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Wed, 27 Mar 2024 11:05:21 -0400 Subject: [PATCH 6/9] Test offline peer onion message interception. --- .../src/onion_message/functional_tests.rs | 102 ++++++++++++++++-- 1 file changed, 96 insertions(+), 6 deletions(-) diff --git a/lightning/src/onion_message/functional_tests.rs b/lightning/src/onion_message/functional_tests.rs index 41878ed1b9c..eb0b17246c3 100644 --- a/lightning/src/onion_message/functional_tests.rs +++ b/lightning/src/onion_message/functional_tests.rs @@ -59,6 +59,17 @@ struct MessengerNode { >> } +impl Drop for MessengerNode { + fn drop(&mut self) { + #[cfg(feature = "std")] { + if std::thread::panicking() { + return; + } + } + assert!(release_events(self).is_empty()); + } +} + struct TestOffersMessageHandler {} impl OffersMessageHandler for TestOffersMessageHandler { @@ -164,15 +175,20 @@ fn create_nodes(num_messengers: u8) -> Vec { struct MessengerCfg { secret_override: Option, + intercept_offline_peer_oms: bool, } impl MessengerCfg { fn new() -> Self { - Self { secret_override: None } + Self { secret_override: None, intercept_offline_peer_oms: false } } fn with_node_secret(mut self, secret: SecretKey) -> Self { self.secret_override = Some(secret); self } + fn with_offline_peer_interception(mut self) -> Self { + self.intercept_offline_peer_oms = true; + self + } } fn create_nodes_using_cfgs(cfgs: Vec) -> Vec { @@ -196,14 +212,24 @@ fn create_nodes_using_cfgs(cfgs: Vec) -> Vec { ); let offers_message_handler = Arc::new(TestOffersMessageHandler {}); let custom_message_handler = Arc::new(TestCustomMessageHandler::new()); + let messenger = if cfg.intercept_offline_peer_oms { + OnionMessenger::new_with_offline_peer_interception( + entropy_source.clone(), node_signer.clone(), logger.clone(), + node_id_lookup, message_router, offers_message_handler, + custom_message_handler.clone() + ) + } else { + OnionMessenger::new( + entropy_source.clone(), node_signer.clone(), logger.clone(), + node_id_lookup, message_router, offers_message_handler, + custom_message_handler.clone() + ) + }; nodes.push(MessengerNode { privkey: secret_key, node_id: node_signer.get_node_id(Recipient::Node).unwrap(), - entropy_source: entropy_source.clone(), - messenger: OnionMessenger::new( - entropy_source, node_signer, logger.clone(), node_id_lookup, message_router, - offers_message_handler, custom_message_handler.clone() - ), + entropy_source, + messenger, custom_message_handler, gossip_sync: gossip_sync.clone(), }); @@ -552,6 +578,70 @@ fn drops_buffered_messages_waiting_for_peer_connection() { assert!(nodes[0].messenger.next_onion_message_for_peer(nodes[1].node_id).is_none()); } +#[test] +fn intercept_offline_peer_oms() { + // Ensure that if OnionMessenger is initialized with + // new_with_offline_peer_interception, we will intercept OMs for offline + // peers, generate the right events, and forward OMs when they are re-injected + // by the user. + let node_cfgs = vec![MessengerCfg::new(), MessengerCfg::new().with_offline_peer_interception(), MessengerCfg::new()]; + let mut nodes = create_nodes_using_cfgs(node_cfgs); + + let peer_conn_evs = release_events(&nodes[1]); + assert_eq!(peer_conn_evs.len(), 2); + for (i, ev) in peer_conn_evs.iter().enumerate() { + match ev { + Event::OnionMessagePeerConnected { peer_node_id } => { + let node_idx = if i == 0 { 0 } else { 2 }; + assert_eq!(peer_node_id, &nodes[node_idx].node_id); + }, + _ => panic!() + } + } + + let message = TestCustomMessage::Response; + let secp_ctx = Secp256k1::new(); + let blinded_path = BlindedPath::new_for_message( + &[nodes[1].node_id, nodes[2].node_id], &*nodes[2].entropy_source, &secp_ctx + ).unwrap(); + let destination = Destination::BlindedPath(blinded_path); + + // Disconnect the peers to ensure we intercept the OM. + disconnect_peers(&nodes[1], &nodes[2]); + nodes[0].messenger.send_onion_message(message, destination, None).unwrap(); + let mut final_node_vec = nodes.split_off(2); + pass_along_path(&nodes); + + let mut events = release_events(&nodes[1]); + assert_eq!(events.len(), 1); + let onion_message = match events.remove(0) { + Event::OnionMessageIntercepted { peer_node_id, message } => { + assert_eq!(peer_node_id, final_node_vec[0].node_id); + message + }, + _ => panic!() + }; + + // Ensure that we'll refuse to forward the re-injected OM until after the + // outbound peer comes back online. + let err = nodes[1].messenger.forward_onion_message(onion_message.clone(), &final_node_vec[0].node_id).unwrap_err(); + assert_eq!(err, SendError::InvalidFirstHop(final_node_vec[0].node_id)); + + connect_peers(&nodes[1], &final_node_vec[0]); + let peer_conn_ev = release_events(&nodes[1]); + assert_eq!(peer_conn_ev.len(), 1); + match peer_conn_ev[0] { + Event::OnionMessagePeerConnected { peer_node_id } => { + assert_eq!(peer_node_id, final_node_vec[0].node_id); + }, + _ => panic!() + } + + nodes[1].messenger.forward_onion_message(onion_message, &final_node_vec[0].node_id).unwrap(); + final_node_vec[0].custom_message_handler.expect_message(TestCustomMessage::Response); + pass_along_path(&vec![nodes.remove(1), final_node_vec.remove(0)]); +} + #[test] fn spec_test_vector() { let node_cfgs = [ From 6613f1f0d2b8c8967e8c98efda136cdbe837ae9a Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Wed, 27 Mar 2024 11:06:33 -0400 Subject: [PATCH 7/9] Manually implement Debug for onion message packets. Previously we derived Debug, but that caused a lot of unreadable encrypted bytes to be printed. --- lightning/src/onion_message/packet.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lightning/src/onion_message/packet.rs b/lightning/src/onion_message/packet.rs index 510f0ea025a..7483888d137 100644 --- a/lightning/src/onion_message/packet.rs +++ b/lightning/src/onion_message/packet.rs @@ -24,6 +24,7 @@ use crate::util::logger::Logger; use crate::util::ser::{BigSize, FixedLengthReader, LengthRead, LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer}; use core::cmp; +use core::fmt; use crate::io::{self, Read}; use crate::prelude::*; @@ -33,7 +34,7 @@ pub(super) const SMALL_PACKET_HOP_DATA_LEN: usize = 1300; pub(super) const BIG_PACKET_HOP_DATA_LEN: usize = 32768; /// Packet of hop data for next peer -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Hash, PartialEq, Eq)] pub struct Packet { /// Bolt 04 version number pub version: u8, @@ -62,6 +63,12 @@ impl onion_utils::Packet for Packet { } } +impl fmt::Debug for Packet { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_fmt(format_args!("Onion message packet version {} with hmac {:?}", self.version, &self.hmac[..])) + } +} + impl Writeable for Packet { fn write(&self, w: &mut W) -> Result<(), io::Error> { self.version.write(w)?; From edc86e319f48b9a3f0aff9653a2bed8b2c70d1b9 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Wed, 27 Mar 2024 10:09:47 -0400 Subject: [PATCH 8/9] Limit OnionMessenger event buffer size. --- lightning/src/onion_message/messenger.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index 213ac7fc9e7..e71066561ec 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -1007,6 +1007,20 @@ where } msgs } + + fn enqueue_event(&self, event: Event) { + const MAX_EVENTS_BUFFER_SIZE: usize = (1 << 10) * 256; + let mut pending_events = self.pending_events.lock().unwrap(); + let total_buffered_bytes: usize = pending_events + .iter() + .map(|ev| ev.serialized_length()) + .sum(); + if total_buffered_bytes >= MAX_EVENTS_BUFFER_SIZE { + log_trace!(self.logger, "Dropping event {:?}: buffer full", event); + return + } + pending_events.push(event); + } } fn outbound_buffer_full(peer_node_id: &PublicKey, buffer: &HashMap) -> bool { @@ -1134,7 +1148,7 @@ where log_trace!(logger, "Forwarding an onion message to peer {}", next_node_id); }, _ if self.intercept_messages_for_offline_peers => { - self.pending_events.lock().unwrap().push( + self.enqueue_event( Event::OnionMessageIntercepted { peer_node_id: next_node_id, message: onion_message } @@ -1162,7 +1176,7 @@ where .or_insert_with(|| OnionMessageRecipient::ConnectedPeer(VecDeque::new())) .mark_connected(); if self.intercept_messages_for_offline_peers { - self.pending_events.lock().unwrap().push( + self.enqueue_event( Event::OnionMessagePeerConnected { peer_node_id: *their_node_id } ); } From a5ada64866880ee355eccabaf30abff7fb628927 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Wed, 27 Mar 2024 11:52:10 -0400 Subject: [PATCH 9/9] Fill in top-level docs for onion message offline peer interception. --- lightning/src/onion_message/messenger.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index e71066561ec..60004acfba7 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -805,7 +805,27 @@ where ) } + /// Similar to [`Self::new`], but rather than dropping onion messages that are + /// intended to be forwarded to offline peers, we will intercept them for + /// later forwarding. /// + /// Interception flow: + /// 1. If an onion message for an offline peer is received, `OnionMessenger` will + /// generate an [`Event::OnionMessageIntercepted`]. Event handlers can + /// then choose to persist this onion message for later forwarding, or drop + /// it. + /// 2. When the offline peer later comes back online, `OnionMessenger` will + /// generate an [`Event::OnionMessagePeerConnected`]. Event handlers will + /// then fetch all previously intercepted onion messages for this peer. + /// 3. Once the stored onion messages are fetched, they can finally be + /// forwarded to the now-online peer via [`Self::forward_onion_message`]. + /// + /// # Note + /// + /// LDK will not rate limit how many [`Event::OnionMessageIntercepted`]s + /// are generated, so it is the caller's responsibility to limit how many + /// onion messages are persisted and only persist onion messages for relevant + /// peers. pub fn new_with_offline_peer_interception( entropy_source: ES, node_signer: NS, logger: L, node_id_lookup: NL, message_router: MR, offers_handler: OMH, custom_handler: CMH