Skip to content

Commit 23110c0

Browse files
committed
Introduce ResponseInstruction::WithReplyPath variant.
And expand handle_onion_message_response return Type 1. Introduce a new function in OnionMessenger to create blinded paths. 2. Use it in handle_onion_message_response to create a reply_path for the right variant and use it in onion_message. 3. Expand the return type of handle_onion_message_response to handle three cases: 1. Ok(None) in case of no response to be sent. 2. Ok(Some(SendSuccess) and Err(SendError) in case of successful and unsuccessful queueing up of response messages respectively. This allows the user to get access to the Success/Failure status of the sending of response and handle it accordingly.
1 parent fdca6f0 commit 23110c0

File tree

2 files changed

+88
-18
lines changed

2 files changed

+88
-18
lines changed

lightning/src/onion_message/functional_tests.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::routing::test_utils::{add_channel, add_or_update_node};
1919
use crate::sign::{NodeSigner, Recipient};
2020
use crate::util::ser::{FixedLengthReader, LengthReadable, Writeable, Writer};
2121
use crate::util::test_utils;
22-
use super::messenger::{CustomOnionMessageHandler, DefaultMessageRouter, Destination, OnionMessagePath, OnionMessenger, PendingOnionMessage, Responder, ResponseInstruction, SendError};
22+
use super::messenger::{CustomOnionMessageHandler, DefaultMessageRouter, Destination, OnionMessagePath, OnionMessenger, PendingOnionMessage, Responder, ResponseInstruction, SendError, SendSuccess};
2323
use super::offers::{OffersMessage, OffersMessageHandler};
2424
use super::packet::{OnionMessageContents, Packet};
2525

@@ -397,7 +397,11 @@ fn async_response_over_one_blinded_hop() {
397397
let response_instruction = nodes[0].custom_message_handler.handle_custom_message(message, responder);
398398

399399
// 6. Simulate Alice asynchronously responding back to Bob with a response.
400-
nodes[0].messenger.handle_onion_message_response(response_instruction);
400+
assert_eq!(
401+
nodes[0].messenger.handle_onion_message_response(response_instruction),
402+
Ok(Some(SendSuccess::Buffered)),
403+
);
404+
401405
bob.custom_message_handler.expect_message(TestCustomMessage::Response);
402406

403407
pass_along_path(&nodes);

lightning/src/onion_message/messenger.rs

Lines changed: 82 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -271,14 +271,27 @@ impl Responder {
271271
}
272272
}
273273

274-
/// Creates the appropriate [`ResponseInstruction`] for a given response.
274+
/// Creates a [`ResponseInstruction::WithoutReplyPath`] for a given response.
275+
///
276+
/// Use when the recipient doesn't need to send back a reply to us.
275277
pub fn respond<T: OnionMessageContents>(self, response: T) -> ResponseInstruction<T> {
276278
ResponseInstruction::WithoutReplyPath(OnionMessageResponse {
277279
message: response,
278280
reply_path: self.reply_path,
279281
path_id: self.path_id,
280282
})
281283
}
284+
285+
/// Creates a [`ResponseInstruction::WithReplyPath`] for a given response.
286+
///
287+
/// Use when the recipient needs to send back a reply to us.
288+
pub fn respond_with_reply_path<T: OnionMessageContents>(self, response: T) -> ResponseInstruction<T> {
289+
ResponseInstruction::WithReplyPath(OnionMessageResponse {
290+
message: response,
291+
reply_path: self.reply_path,
292+
path_id: self.path_id,
293+
})
294+
}
282295
}
283296

284297
/// This struct contains the information needed to reply to a received message.
@@ -290,6 +303,9 @@ pub struct OnionMessageResponse<T: OnionMessageContents> {
290303

291304
/// `ResponseInstruction` represents instructions for responding to received messages.
292305
pub enum ResponseInstruction<T: OnionMessageContents> {
306+
/// Indicates that a response should be sent including a reply path for
307+
/// the recipient to respond back.
308+
WithReplyPath(OnionMessageResponse<T>),
293309
/// Indicates that a response should be sent without including a reply path
294310
/// for the recipient to respond back.
295311
WithoutReplyPath(OnionMessageResponse<T>),
@@ -564,7 +580,11 @@ pub enum SendError {
564580
TooFewBlindedHops,
565581
/// The first hop is not a peer and doesn't have a known [`SocketAddress`].
566582
InvalidFirstHop(PublicKey),
567-
/// A path from the sender to the destination could not be found by the [`MessageRouter`].
583+
/// Indicates that a path could not be found by the [`MessageRouter`].
584+
///
585+
/// This occurs when either:
586+
/// - No path from the sender to the destination was found to send the onion message
587+
/// - No reply path to the sender could be created when responding to an onion message
568588
PathNotFound,
569589
/// Onion message contents must have a TLV type >= 64.
570590
InvalidMessage,
@@ -981,6 +1001,33 @@ where
9811001
.map_err(|_| SendError::PathNotFound)
9821002
}
9831003

1004+
fn create_blinded_path(&self) -> Result<BlindedPath, SendError> {
1005+
let recipient = self.node_signer
1006+
.get_node_id(Recipient::Node)
1007+
.map_err(|_| SendError::GetNodeIdFailed)?;
1008+
let secp_ctx = &self.secp_ctx;
1009+
1010+
// let peers = self.message_recipients.lock().unwrap()
1011+
// .iter()
1012+
// .filter(|(_, peer)| matches!(peer, OnionMessageRecipient::ConnectedPeer(_)))
1013+
// .map(|(node_id, _)| *node_id)
1014+
// .collect();
1015+
1016+
let peers = self.message_recipients.lock().unwrap()
1017+
.iter()
1018+
.filter(|(_, peer)| matches!(peer, OnionMessageRecipient::ConnectedPeer(_)))
1019+
.map(|(node_id, _ )| ForwardNode {
1020+
node_id: *node_id,
1021+
short_channel_id: None,
1022+
})
1023+
.collect::<Vec<_>>();
1024+
1025+
self.message_router
1026+
.create_blinded_paths(recipient, peers, secp_ctx)
1027+
.and_then(|paths| paths.into_iter().next().ok_or(()))
1028+
.map_err(|_| SendError::PathNotFound)
1029+
}
1030+
9841031
fn enqueue_onion_message<T: OnionMessageContents>(
9851032
&self, path: OnionMessagePath, contents: T, reply_path: Option<BlindedPath>,
9861033
log_suffix: fmt::Arguments
@@ -1065,18 +1112,37 @@ where
10651112
/// the response for delivery.
10661113
pub fn handle_onion_message_response<T: OnionMessageContents>(
10671114
&self, response: ResponseInstruction<T>
1068-
) {
1069-
if let ResponseInstruction::WithoutReplyPath(response) = response {
1070-
let message_type = response.message.msg_type();
1071-
let _ = self.find_path_and_enqueue_onion_message(
1072-
response.message, Destination::BlindedPath(response.reply_path), None,
1073-
format_args!(
1074-
"when responding with {} to an onion message with path_id {:02x?}",
1075-
message_type,
1076-
response.path_id
1077-
)
1078-
);
1079-
}
1115+
) -> Result<Option<SendSuccess>, SendError> {
1116+
let (response, create_reply_path) = match response {
1117+
ResponseInstruction::WithReplyPath(response) => (response, true),
1118+
ResponseInstruction::WithoutReplyPath(response) => (response, false),
1119+
ResponseInstruction::NoResponse => return Ok(None),
1120+
};
1121+
1122+
let message_type = response.message.msg_type();
1123+
let reply_path = if create_reply_path {
1124+
match self.create_blinded_path() {
1125+
Ok(reply_path) => Some(reply_path),
1126+
Err(err) => {
1127+
log_trace!(
1128+
self.logger,
1129+
"Failed to create reply path when responding with {} to an onion message \
1130+
with path_id {:02x?}: {:?}",
1131+
message_type, response.path_id, err
1132+
);
1133+
return Err(err);
1134+
}
1135+
}
1136+
} else { None };
1137+
1138+
self.find_path_and_enqueue_onion_message(
1139+
response.message, Destination::BlindedPath(response.reply_path), reply_path,
1140+
format_args!(
1141+
"when responding with {} to an onion message with path_id {:02x?}",
1142+
message_type,
1143+
response.path_id
1144+
)
1145+
).map(|result| Some(result))
10801146
}
10811147

10821148
#[cfg(test)]
@@ -1182,14 +1248,14 @@ where
11821248
|reply_path| Responder::new(reply_path, path_id)
11831249
);
11841250
let response_instructions = self.offers_handler.handle_message(msg, responder);
1185-
self.handle_onion_message_response(response_instructions);
1251+
let _ = self.handle_onion_message_response(response_instructions);
11861252
},
11871253
ParsedOnionMessageContents::Custom(msg) => {
11881254
let responder = reply_path.map(
11891255
|reply_path| Responder::new(reply_path, path_id)
11901256
);
11911257
let response_instructions = self.custom_handler.handle_custom_message(msg, responder);
1192-
self.handle_onion_message_response(response_instructions);
1258+
let _ = self.handle_onion_message_response(response_instructions);
11931259
},
11941260
}
11951261
},

0 commit comments

Comments
 (0)