Skip to content

Commit a99529d

Browse files
committed
Support onion message replies in OnionMessenger
1 parent 6d7658d commit a99529d

File tree

6 files changed

+150
-20
lines changed

6 files changed

+150
-20
lines changed

fuzz/src/onion_message.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use lightning::ln::script::ShutdownScript;
1111
use lightning::util::enforcing_trait_impls::EnforcingSigner;
1212
use lightning::util::logger::Logger;
1313
use lightning::util::ser::{Readable, Writeable, Writer};
14-
use lightning::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessenger};
14+
use lightning::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessenger, ResponseError, ResponseErrorHandler};
1515

1616
use crate::utils::test_logger;
1717

@@ -66,7 +66,15 @@ impl MessageRouter for TestMessageRouter {
6666
struct TestOffersMessageHandler {}
6767

6868
impl OffersMessageHandler for TestOffersMessageHandler {
69-
fn handle_message(&self, _message: OffersMessage) {}
69+
fn handle_message(&self, _message: OffersMessage) -> Option<OffersMessage> {
70+
None
71+
}
72+
}
73+
74+
impl ResponseErrorHandler for TestOffersMessageHandler {
75+
fn handle_response_error(&self, _error: ResponseError) {
76+
unreachable!()
77+
}
7078
}
7179

7280
struct TestCustomMessage {}
@@ -90,14 +98,22 @@ struct TestCustomMessageHandler {}
9098

9199
impl CustomOnionMessageHandler for TestCustomMessageHandler {
92100
type CustomMessage = TestCustomMessage;
93-
fn handle_custom_message(&self, _msg: Self::CustomMessage) {}
101+
fn handle_custom_message(&self, _msg: Self::CustomMessage) -> Option<Self::CustomMessage> {
102+
None
103+
}
94104
fn read_custom_message<R: io::Read>(&self, _message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, msgs::DecodeError> {
95105
let mut buf = Vec::new();
96106
buffer.read_to_end(&mut buf)?;
97107
return Ok(Some(TestCustomMessage {}))
98108
}
99109
}
100110

111+
impl ResponseErrorHandler for TestCustomMessageHandler {
112+
fn handle_response_error(&self, _error: ResponseError) {
113+
unreachable!()
114+
}
115+
}
116+
101117
pub struct VecWriter(pub Vec<u8>);
102118
impl Writer for VecWriter {
103119
fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> {

lightning/src/ln/peer_handler.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::util::ser::{VecWriter, Writeable, Writer};
2626
use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep};
2727
use crate::ln::wire;
2828
use crate::ln::wire::Encode;
29-
use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, OffersMessage, OffersMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
29+
use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, OffersMessage, OffersMessageHandler, ResponseError, ResponseErrorHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
3030
use crate::routing::gossip::{NetworkGraph, P2PGossipSync};
3131
use crate::util::atomic_counter::AtomicCounter;
3232
use crate::util::events::{MessageSendEvent, MessageSendEventsProvider, OnionMessageProvider};
@@ -95,18 +95,24 @@ impl OnionMessageHandler for IgnoringMessageHandler {
9595
}
9696
}
9797
impl OffersMessageHandler for IgnoringMessageHandler {
98-
fn handle_message(&self, _msg: OffersMessage) {}
98+
fn handle_message(&self, _msg: OffersMessage) -> Option<OffersMessage> { None }
9999
}
100100
impl CustomOnionMessageHandler for IgnoringMessageHandler {
101101
type CustomMessage = Infallible;
102-
fn handle_custom_message(&self, _msg: Infallible) {
102+
fn handle_custom_message(&self, _msg: Infallible) -> Option<Infallible> {
103103
// Since we always return `None` in the read the handle method should never be called.
104104
unreachable!();
105105
}
106106
fn read_custom_message<R: io::Read>(&self, _msg_type: u64, _buffer: &mut R) -> Result<Option<Infallible>, msgs::DecodeError> where Self: Sized {
107107
Ok(None)
108108
}
109109
}
110+
impl ResponseErrorHandler for IgnoringMessageHandler {
111+
fn handle_response_error(&self, _error: ResponseError) {
112+
// Since handler implementations return None for a response.
113+
unreachable!();
114+
}
115+
}
110116

111117
impl CustomOnionMessageContents for Infallible {
112118
fn tlv_type(&self) -> u64 { unreachable!(); }

lightning/src/onion_message/functional_tests.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use crate::chain::keysinterface::{NodeSigner, Recipient};
1313
use crate::ln::features::InitFeatures;
1414
use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
15-
use super::{BlindedPath, CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessageContents, OnionMessenger, SendError};
15+
use super::{BlindedPath, CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessageContents, OnionMessenger, ResponseError, ResponseErrorHandler, SendError};
1616
use crate::util::ser::{Writeable, Writer};
1717
use crate::util::test_utils;
1818

@@ -52,7 +52,13 @@ impl MessageRouter for TestMessageRouter {
5252
struct TestOffersMessageHandler {}
5353

5454
impl OffersMessageHandler for TestOffersMessageHandler {
55-
fn handle_message(&self, _message: OffersMessage) {
55+
fn handle_message(&self, _message: OffersMessage) -> Option<OffersMessage> {
56+
todo!()
57+
}
58+
}
59+
60+
impl ResponseErrorHandler for TestOffersMessageHandler {
61+
fn handle_response_error(&self, _error: ResponseError) {
5662
todo!()
5763
}
5864
}
@@ -79,7 +85,9 @@ struct TestCustomMessageHandler {}
7985

8086
impl CustomOnionMessageHandler for TestCustomMessageHandler {
8187
type CustomMessage = TestCustomMessage;
82-
fn handle_custom_message(&self, _msg: Self::CustomMessage) {}
88+
fn handle_custom_message(&self, _msg: Self::CustomMessage) -> Option<Self::CustomMessage> {
89+
None
90+
}
8391
fn read_custom_message<R: io::Read>(&self, message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, DecodeError> where Self: Sized {
8492
if message_type == CUSTOM_MESSAGE_TYPE {
8593
let mut buf = Vec::new();
@@ -91,6 +99,12 @@ impl CustomOnionMessageHandler for TestCustomMessageHandler {
9199
}
92100
}
93101

102+
impl ResponseErrorHandler for TestCustomMessageHandler {
103+
fn handle_response_error(&self, _error: ResponseError) {
104+
todo!()
105+
}
106+
}
107+
94108
fn create_nodes(num_messengers: u8) -> Vec<MessengerNode> {
95109
let mut nodes = Vec::new();
96110
for i in 0..num_messengers {

lightning/src/onion_message/messenger.rs

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -200,17 +200,36 @@ pub enum SendError {
200200
///
201201
/// [`IgnoringMessageHandler`]: crate::ln::peer_handler::IgnoringMessageHandler
202202
/// [`CustomMessage`]: Self::CustomMessage
203-
pub trait CustomOnionMessageHandler {
203+
pub trait CustomOnionMessageHandler: ResponseErrorHandler {
204204
/// The message known to the handler. To support multiple message types, you may want to make this
205205
/// an enum with a variant for each supported message.
206206
type CustomMessage: CustomOnionMessageContents;
207-
/// Called with the custom message that was received.
208-
fn handle_custom_message(&self, msg: Self::CustomMessage);
207+
208+
/// Called with the custom message that was received, returning a response to send, if any.
209+
fn handle_custom_message(&self, msg: Self::CustomMessage) -> Option<Self::CustomMessage>;
210+
209211
/// Read a custom message of type `message_type` from `buffer`, returning `Ok(None)` if the
210212
/// message type is unknown.
211213
fn read_custom_message<R: io::Read>(&self, message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, msgs::DecodeError>;
212214
}
213215

216+
///
217+
pub trait ResponseErrorHandler {
218+
/// Called if an error occurred when sending a response to the handled message.
219+
fn handle_response_error(&self, error: ResponseError);
220+
}
221+
222+
///
223+
#[derive(Debug, PartialEq, Eq)]
224+
pub enum ResponseError {
225+
///
226+
GetNodeIdFailed,
227+
///
228+
NoReplyPath,
229+
///
230+
Sending(SendError),
231+
}
232+
214233
impl<ES: Deref, NS: Deref, L: Deref, MR: Deref, OMH: Deref, CMH: Deref>
215234
OnionMessenger<ES, NS, L, MR, OMH, CMH>
216235
where
@@ -295,6 +314,45 @@ where
295314
}
296315
}
297316

317+
fn respond_with_onion_message<T: CustomOnionMessageContents, EH: ResponseErrorHandler>(
318+
&self, response: OnionMessageContents<T>, path_id: Option<[u8; 32]>,
319+
reply_path: Option<BlindedPath>, error_handler: &EH
320+
) {
321+
let sender = match self.node_signer.get_node_id(Recipient::Node) {
322+
Ok(node_id) => node_id,
323+
Err(_) => {
324+
log_info!(
325+
self.logger, "No sender to respond to onion message with path_id {:02x?}",
326+
path_id
327+
);
328+
return error_handler.handle_response_error(ResponseError::GetNodeIdFailed);
329+
}
330+
};
331+
332+
let destination = match reply_path {
333+
Some(reply_path) => Destination::BlindedPath(reply_path),
334+
None => {
335+
log_info!(
336+
self.logger, "No reply path to respond to onion message with path_id {:02x?}",
337+
path_id
338+
);
339+
return error_handler.handle_response_error(ResponseError::NoReplyPath);
340+
},
341+
};
342+
343+
let intermediate_nodes = self.message_router.find_route(&sender, &destination);
344+
345+
log_info!(self.logger, "Responding to onion message with path_id {:02x?}", path_id);
346+
347+
if let Err(e) = self.send_onion_message(&intermediate_nodes, destination, response, None) {
348+
log_info!(
349+
self.logger, "Failed responding to onion message with path_id {:02x?}: {:?}",
350+
path_id, e
351+
);
352+
return error_handler.handle_response_error(ResponseError::Sending(e));
353+
}
354+
}
355+
298356
#[cfg(test)]
299357
pub(super) fn release_pending_msgs(&self) -> HashMap<PublicKey, VecDeque<msgs::OnionMessage>> {
300358
let mut pending_msgs = self.pending_messages.lock().unwrap();
@@ -338,7 +396,7 @@ where
338396
NS::Target: NodeSigner,
339397
L::Target: Logger,
340398
MR::Target: MessageRouter,
341-
OMH::Target: OffersMessageHandler,
399+
OMH::Target: OffersMessageHandler + Sized,
342400
CMH::Target: CustomOnionMessageHandler + Sized,
343401
{
344402
/// Handle an incoming onion message. Currently, if a message was destined for us we will log, but
@@ -377,9 +435,27 @@ where
377435
log_info!(self.logger,
378436
"Received an onion message with path_id {:02x?} and {} reply_path",
379437
path_id, if reply_path.is_some() { "a" } else { "no" });
380-
match message {
381-
OnionMessageContents::Offers(msg) => self.offers_handler.handle_message(msg),
382-
OnionMessageContents::Custom(msg) => self.custom_handler.handle_custom_message(msg),
438+
439+
let response = match message {
440+
OnionMessageContents::Offers(msg) => {
441+
self.offers_handler.handle_message(msg)
442+
.map(|msg| OnionMessageContents::Offers(msg))
443+
},
444+
OnionMessageContents::Custom(msg) => {
445+
self.custom_handler.handle_custom_message(msg)
446+
.map(|msg| OnionMessageContents::Custom(msg))
447+
},
448+
};
449+
450+
if let Some(response) = response {
451+
match response {
452+
OnionMessageContents::Offers(_) => self.respond_with_onion_message(
453+
response, path_id, reply_path, &*self.offers_handler
454+
),
455+
OnionMessageContents::Custom(_) => self.respond_with_onion_message(
456+
response, path_id, reply_path, &*self.custom_handler
457+
),
458+
}
383459
}
384460
},
385461
Ok((Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs {

lightning/src/onion_message/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ mod functional_tests;
3030

3131
// Re-export structs so they can be imported with just the `onion_message::` module prefix.
3232
pub use self::blinded_path::{BlindedPath, BlindedHop};
33-
pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OnionMessageContents, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
33+
pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OnionMessageContents, OnionMessenger, ResponseError, ResponseErrorHandler, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
3434
pub use self::offers::{OffersMessage, OffersMessageHandler};
3535
pub(crate) use self::packet::Packet;

lightning/src/onion_message/offers.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::ln::msgs::DecodeError;
2020
use crate::offers::invoice_request::InvoiceRequest;
2121
use crate::offers::invoice::Invoice;
2222
use crate::offers::parse::ParseError;
23+
use crate::onion_message::messenger::{ResponseError, ResponseErrorHandler};
2324
use crate::routing::router::Router;
2425
use crate::util::logger::Logger;
2526
use crate::util::ser::{ReadableArgs, Writeable, Writer};
@@ -34,10 +35,10 @@ const INVOICE_ERROR_TLV_TYPE: u64 = 68;
3435
/// A handler for an [`OnionMessage`] containing a BOLT 12 Offers message as its payload.
3536
///
3637
/// [`OnionMessage`]: crate::ln::msgs::OnionMessage
37-
pub trait OffersMessageHandler {
38+
pub trait OffersMessageHandler: ResponseErrorHandler {
3839
/// Handles the given message by either responding with an [`Invoice`], sending a payment, or
3940
/// replying with an error.
40-
fn handle_message(&self, message: OffersMessage);
41+
fn handle_message(&self, message: OffersMessage) -> Option<OffersMessage>;
4142
}
4243

4344
/// Possible BOLT 12 Offers messages sent and received via an [`OnionMessage`].
@@ -122,7 +123,24 @@ where
122123
R::Target: Router,
123124
L::Target: Logger,
124125
{
125-
fn handle_message(&self, _message: OffersMessage) {
126+
fn handle_message(&self, _message: OffersMessage) -> Option<OffersMessage> {
127+
todo!()
128+
}
129+
}
130+
131+
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>
132+
ResponseErrorHandler for ChannelManager<M, T, ES, NS, SP, F, R, L>
133+
where
134+
M::Target: chain::Watch<<SP::Target as SignerProvider>::Signer>,
135+
T::Target: BroadcasterInterface,
136+
ES::Target: EntropySource,
137+
NS::Target: NodeSigner,
138+
SP::Target: SignerProvider,
139+
F::Target: FeeEstimator,
140+
R::Target: Router,
141+
L::Target: Logger,
142+
{
143+
fn handle_response_error(&self, _error: ResponseError) {
126144
todo!()
127145
}
128146
}

0 commit comments

Comments
 (0)