Skip to content

Commit 8d74148

Browse files
committed
Enqueue onion messages in handlers
When constructing onion messages to send initially (opposed to replying to one from a handler), the user must construct an OnionMessagePath first before calling OnionMessener::send_onion_message. Additionally, having a reference to OnionMessener isn't always desirable. For instance, in an upcoming commit, ChannelManager will implement OffersMessageHandler, which OnionMessenger needs a reference to. If ChannelManager had a reference to OnionMessenger, too, there would be a dependency cycle. Instead, modify OffersMessageHandler and CustomOnionMessageHandler's interfaces to include a method for releasing pending onion messages. That way, ChannelManager may, for instance, construct and enqueue an InvoiceRequest for sending without needing a reference to OnionMessenger. Additionally, OnionMessenger has responsibility for path finding just as it does when replying to messages from a handler. It performs this when extracting messages from the handlers before returning the next message to send to a peer.
1 parent 46c5d9e commit 8d74148

File tree

6 files changed

+80
-7
lines changed

6 files changed

+80
-7
lines changed

fuzz/src/onion_message.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use lightning::offers::invoice_request::UnsignedInvoiceRequest;
1414
use lightning::util::test_channel_signer::TestChannelSigner;
1515
use lightning::util::logger::Logger;
1616
use lightning::util::ser::{Readable, Writeable, Writer};
17-
use lightning::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessagePath, OnionMessenger};
17+
use lightning::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessagePath, OnionMessenger, PendingOnionMessage};
1818

1919
use crate::utils::test_logger;
2020

@@ -108,6 +108,9 @@ impl CustomOnionMessageHandler for TestCustomMessageHandler {
108108
buffer.read_to_end(&mut buf)?;
109109
return Ok(Some(TestCustomMessage {}))
110110
}
111+
fn release_pending_custom_messages(&self) -> Vec<PendingOnionMessage<Self::CustomMessage>> {
112+
vec![]
113+
}
111114
}
112115

113116
pub struct VecWriter(pub Vec<u8>);

lightning/src/ln/peer_handler.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use crate::util::ser::{VecWriter, Writeable, Writer};
2929
use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep};
3030
use crate::ln::wire;
3131
use crate::ln::wire::{Encode, Type};
32-
use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, OffersMessage, OffersMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
32+
use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, OffersMessage, OffersMessageHandler, PendingOnionMessage, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
3333
use crate::routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, NodeAlias};
3434
use crate::util::atomic_counter::AtomicCounter;
3535
use crate::util::logger::Logger;
@@ -129,6 +129,9 @@ impl CustomOnionMessageHandler for IgnoringMessageHandler {
129129
fn read_custom_message<R: io::Read>(&self, _msg_type: u64, _buffer: &mut R) -> Result<Option<Infallible>, msgs::DecodeError> where Self: Sized {
130130
Ok(None)
131131
}
132+
fn release_pending_custom_messages(&self) -> Vec<PendingOnionMessage<Infallible>> {
133+
vec![]
134+
}
132135
}
133136

134137
impl CustomOnionMessageContents for Infallible {

lightning/src/onion_message/functional_tests.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
1515
use crate::sign::{NodeSigner, Recipient};
1616
use crate::util::ser::{FixedLengthReader, LengthReadable, Writeable, Writer};
1717
use crate::util::test_utils;
18-
use super::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessageContents, OnionMessagePath, OnionMessenger, SendError};
18+
use super::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessageContents, OnionMessagePath, OnionMessenger, PendingOnionMessage, SendError};
1919

2020
use bitcoin::network::constants::Network;
2121
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
@@ -148,6 +148,9 @@ impl CustomOnionMessageHandler for TestCustomMessageHandler {
148148
_ => Ok(None),
149149
}
150150
}
151+
fn release_pending_custom_messages(&self) -> Vec<PendingOnionMessage<Self::CustomMessage>> {
152+
vec![]
153+
}
151154
}
152155

153156
fn create_nodes(num_messengers: u8) -> Vec<MessengerNode> {

lightning/src/onion_message/messenger.rs

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,28 @@ where
155155
custom_handler: CMH,
156156
}
157157

158+
/// An [`OnionMessage`] for [`OnionMessenger`] to send.
159+
///
160+
/// These are obtained when released from [`OnionMessenger`]'s handlers after which they are
161+
/// enqueued for sending.
162+
///
163+
/// [`OnionMessage`]: crate::ln::msgs::OnionMessage
164+
pub struct PendingOnionMessage<T> {
165+
/// The message contents to send in an [`OnionMessage`].
166+
///
167+
/// [`OnionMessage`]: crate::ln::msgs::OnionMessage
168+
pub contents: T,
169+
170+
/// The destination of the message.
171+
pub destination: Destination,
172+
173+
/// A reply path to include in the [`OnionMessage`] for a response.
174+
///
175+
/// [`OnionMessage`]: crate::ln::msgs::OnionMessage
176+
pub reply_path: Option<BlindedPath>,
177+
178+
}
179+
158180
/// A trait defining behavior for routing an [`OnionMessage`].
159181
///
160182
/// [`OnionMessage`]: msgs::OnionMessage
@@ -252,11 +274,19 @@ pub trait CustomOnionMessageHandler {
252274
type CustomMessage: CustomOnionMessageContents;
253275

254276
/// Called with the custom message that was received, returning a response to send, if any.
277+
///
278+
/// The returned [`Self::CustomMessage`], if any, is enqueued to be sent by [`OnionMessenger`].
255279
fn handle_custom_message(&self, msg: Self::CustomMessage) -> Option<Self::CustomMessage>;
256280

257281
/// Read a custom message of type `message_type` from `buffer`, returning `Ok(None)` if the
258282
/// message type is unknown.
259283
fn read_custom_message<R: io::Read>(&self, message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, msgs::DecodeError>;
284+
285+
/// Releases any [`Self::CustomMessage`]s that need to be sent.
286+
///
287+
/// Typically, this is used for messages initiating a message flow rather than in response to
288+
/// another message. The latter should use the return value of [`Self::handle_custom_message`].
289+
fn release_pending_custom_messages(&self) -> Vec<PendingOnionMessage<Self::CustomMessage>>;
260290
}
261291

262292
impl<ES: Deref, NS: Deref, L: Deref, MR: Deref, OMH: Deref, CMH: Deref>
@@ -350,7 +380,7 @@ where
350380

351381
fn find_path_and_enqueue_onion_message<T: CustomOnionMessageContents>(
352382
&self, contents: OnionMessageContents<T>, destination: Destination,
353-
log_suffix: fmt::Arguments
383+
reply_path: Option<BlindedPath>, log_suffix: fmt::Arguments
354384
) {
355385
let sender = match self.node_signer.get_node_id(Recipient::Node) {
356386
Ok(node_id) => node_id,
@@ -371,7 +401,7 @@ where
371401

372402
log_trace!(self.logger, "Sending onion message {}", log_suffix);
373403

374-
if let Err(e) = self.send_onion_message(path, contents, None) {
404+
if let Err(e) = self.send_onion_message(path, contents, reply_path) {
375405
log_trace!(self.logger, "Failed sending onion message {}: {:?}", log_suffix, e);
376406
return;
377407
}
@@ -476,7 +506,7 @@ where
476506
match reply_path {
477507
Some(reply_path) => {
478508
self.find_path_and_enqueue_onion_message(
479-
response, Destination::BlindedPath(reply_path), format_args!(
509+
response, Destination::BlindedPath(reply_path), None, format_args!(
480510
"when responding to onion message with path_id {:02x?}", path_id
481511
)
482512
);
@@ -584,7 +614,30 @@ where
584614
features
585615
}
586616

617+
// Before returning any messages to send for the peer, this method will see if any messages were
618+
// enqueued in the handler by users, find a path to the corresponding blinded path's introduction
619+
// node, and then enqueue the message for sending to the first peer in the full path.
587620
fn next_onion_message_for_peer(&self, peer_node_id: PublicKey) -> Option<msgs::OnionMessage> {
621+
// Enqueue any initiating `OffersMessage`s to send.
622+
for message in self.offers_handler.release_pending_messages() {
623+
let PendingOnionMessage { contents, destination, reply_path } = message;
624+
self.find_path_and_enqueue_onion_message::<
625+
<<CMH as Deref>::Target as CustomOnionMessageHandler>::CustomMessage
626+
>(
627+
OnionMessageContents::Offers(contents), destination, reply_path,
628+
format_args!("when sending OffersMessage")
629+
);
630+
}
631+
632+
// Enqueue any initiating `CustomMessage`s to send.
633+
for message in self.custom_handler.release_pending_custom_messages() {
634+
let PendingOnionMessage { contents, destination, reply_path } = message;
635+
self.find_path_and_enqueue_onion_message(
636+
OnionMessageContents::Custom(contents), destination, reply_path,
637+
format_args!("when sending CustomMessage")
638+
);
639+
}
640+
588641
let mut pending_msgs = self.pending_messages.lock().unwrap();
589642
if let Some(msgs) = pending_msgs.get_mut(&peer_node_id) {
590643
return msgs.pop_front()

lightning/src/onion_message/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ mod packet;
2727
mod functional_tests;
2828

2929
// Re-export structs so they can be imported with just the `onion_message::` module prefix.
30-
pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, DefaultMessageRouter, Destination, MessageRouter, OnionMessageContents, OnionMessagePath, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
30+
pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, DefaultMessageRouter, Destination, MessageRouter, OnionMessageContents, OnionMessagePath, OnionMessenger, PendingOnionMessage, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
3131
pub use self::offers::{OffersMessage, OffersMessageHandler};
3232
pub(crate) use self::packet::{ControlTlvs, Packet};

lightning/src/onion_message/offers.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::offers::invoice_error::InvoiceError;
1616
use crate::offers::invoice_request::InvoiceRequest;
1717
use crate::offers::invoice::Bolt12Invoice;
1818
use crate::offers::parse::Bolt12ParseError;
19+
use crate::onion_message::messenger::PendingOnionMessage;
1920
use crate::util::logger::Logger;
2021
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
2122

@@ -32,7 +33,17 @@ const INVOICE_ERROR_TLV_TYPE: u64 = 68;
3233
pub trait OffersMessageHandler {
3334
/// Handles the given message by either responding with an [`Bolt12Invoice`], sending a payment,
3435
/// or replying with an error.
36+
///
37+
/// The returned [`OffersMessage`], if any, is enqueued to be sent by [`OnionMessenger`].
38+
///
39+
/// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger
3540
fn handle_message(&self, message: OffersMessage) -> Option<OffersMessage>;
41+
42+
/// Releases any [`OffersMessage`]s that need to be sent.
43+
///
44+
/// Typically, this is used for messages initiating a payment flow rather than in response to
45+
/// another message. The latter should use the return value of [`Self::handle_message`].
46+
fn release_pending_messages(&self) -> Vec<PendingOnionMessage<OffersMessage>> { vec![] }
3647
}
3748

3849
/// Possible BOLT 12 Offers messages sent and received via an [`OnionMessage`].

0 commit comments

Comments
 (0)