Skip to content

Commit

Permalink
Introduce ResponseInstruction::WithReplyPath variant.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
shaavan committed May 14, 2024
1 parent f73f8af commit 57bca64
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 17 deletions.
8 changes: 6 additions & 2 deletions lightning/src/onion_message/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::routing::test_utils::{add_channel, add_or_update_node};
use crate::sign::{NodeSigner, Recipient};
use crate::util::ser::{FixedLengthReader, LengthReadable, Writeable, Writer};
use crate::util::test_utils;
use super::messenger::{CustomOnionMessageHandler, DefaultMessageRouter, Destination, OnionMessagePath, OnionMessenger, PendingOnionMessage, Responder, ResponseInstruction, SendError};
use super::messenger::{CustomOnionMessageHandler, DefaultMessageRouter, Destination, OnionMessagePath, OnionMessenger, PendingOnionMessage, Responder, ResponseInstruction, SendError, SendSuccess};
use super::offers::{OffersMessage, OffersMessageHandler};
use super::packet::{OnionMessageContents, Packet};

Expand Down Expand Up @@ -391,7 +391,11 @@ fn async_response_over_one_blinded_hop() {
let response_instruction = nodes[0].custom_message_handler.handle_custom_message(message, responder);

// 6. Simulate Alice asynchronously responding back to Bob with a response.
nodes[0].messenger.handle_onion_message_response(response_instruction);
assert_eq!(
nodes[0].messenger.handle_onion_message_response(response_instruction),
Ok(Some(SendSuccess::Buffered)),
);

bob.custom_message_handler.expect_message(TestCustomMessage::Response);

pass_along_path(&nodes);
Expand Down
82 changes: 67 additions & 15 deletions lightning/src/onion_message/messenger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,14 +267,27 @@ impl Responder {
}
}

/// Creates the appropriate [`ResponseInstruction`] for a given response.
/// Creates a [`ResponseInstruction::WithoutReplyPath`] for a given response.
///
/// Use when the recipient doesn't need to send back a reply to us.
pub fn respond<T: OnionMessageContents>(self, response: T) -> ResponseInstruction<T> {
ResponseInstruction::WithoutReplyPath(OnionMessageResponse {
message: response,
reply_path: self.reply_path,
path_id: self.path_id,
})
}

/// Creates a [`ResponseInstruction::WithReplyPath`] for a given response.
///
/// Use when the recipient need to send back a reply to us.
pub fn respond_with_reply_path<T: OnionMessageContents>(self, response: T) -> ResponseInstruction<T> {
ResponseInstruction::WithReplyPath(OnionMessageResponse {
message: response,
reply_path: self.reply_path,
path_id: self.path_id,
})
}
}

/// This struct contains the information needed to reply to a received message.
Expand All @@ -286,6 +299,9 @@ pub struct OnionMessageResponse<T: OnionMessageContents> {

/// `ResponseInstruction` represents instructions for responding to received messages.
pub enum ResponseInstruction<T: OnionMessageContents> {
/// Indicates that a response should be sent including a reply path for
/// the recipient to respond back.
WithReplyPath(OnionMessageResponse<T>),
/// Indicates that a response should be sent without including a reply path
/// for the recipient to respond back.
WithoutReplyPath(OnionMessageResponse<T>),
Expand Down Expand Up @@ -971,6 +987,24 @@ where
.map_err(|_| SendError::PathNotFound)
}

fn create_blinded_path(&self) -> Result<BlindedPath, SendError> {
let recipient = self.node_signer
.get_node_id(Recipient::Node)
.map_err(|_| SendError::GetNodeIdFailed)?;
let secp_ctx = &self.secp_ctx;

let peers = self.message_recipients.lock().unwrap()
.iter()
.filter(|(_, peer)| matches!(peer, OnionMessageRecipient::ConnectedPeer(_)))
.map(|(node_id, _)| *node_id)
.collect();

self.message_router
.create_blinded_paths(recipient, peers, secp_ctx)
.and_then(|paths| paths.into_iter().next().ok_or(()))
.map_err(|_| SendError::PathNotFound)
}

fn enqueue_onion_message<T: OnionMessageContents>(
&self, path: OnionMessagePath, contents: T, reply_path: Option<BlindedPath>,
log_suffix: fmt::Arguments
Expand Down Expand Up @@ -1047,18 +1081,36 @@ where
/// enqueueing any response for sending.
pub fn handle_onion_message_response<T: OnionMessageContents>(
&self, response: ResponseInstruction<T>
) {
if let ResponseInstruction::WithoutReplyPath(response) = response {
let message_type = response.message.msg_type();
let _ = self.find_path_and_enqueue_onion_message(
response.message, Destination::BlindedPath(response.reply_path), None,
format_args!(
"when responding with {} to an onion message with path_id {:02x?}",
message_type,
response.path_id
)
);
}
) -> Result<Option<SendSuccess>, SendError> {
let (response, create_reply_path) = match response {
ResponseInstruction::WithReplyPath(response) => (response, true),
ResponseInstruction::WithoutReplyPath(response) => (response, false),
ResponseInstruction::NoResponse => return Ok(None),
};

let message_type = response.message.msg_type();
let log_suffix = format!(
"when responding with {} to an onion message with path_id {:02x?}",
message_type,
response.path_id
);

let reply_path = if create_reply_path {
match self.create_blinded_path() {
Ok(reply_path) => Some(reply_path),
Err(e) => {
log_trace!(
self.logger, "Failed to create reply_path {}: {:?}", log_suffix, e
);
return Err(e);
}
}
} else { None };

self.find_path_and_enqueue_onion_message(
response.message, Destination::BlindedPath(response.reply_path), reply_path,
format_args!("{}", log_suffix)
).map(|result| Some(result))
}

#[cfg(test)]
Expand Down Expand Up @@ -1164,14 +1216,14 @@ where
|reply_path| Responder::new(reply_path, path_id)
);
let response_instructions = self.offers_handler.handle_message(msg, responder);
self.handle_onion_message_response(response_instructions);
let _ = self.handle_onion_message_response(response_instructions);
},
ParsedOnionMessageContents::Custom(msg) => {
let responder = reply_path.map(
|reply_path| Responder::new(reply_path, path_id)
);
let response_instructions = self.custom_handler.handle_custom_message(msg, responder);
self.handle_onion_message_response(response_instructions);
let _ = self.handle_onion_message_response(response_instructions);
},
}
},
Expand Down

0 comments on commit 57bca64

Please sign in to comment.