Skip to content

Commit

Permalink
Update handle_message to accept OffersContext data as an input field
Browse files Browse the repository at this point in the history
1. Handling Offers Data:
   - Updated `handle_message` to accept `OffersContext` data as an input field.
   - If it is present, it will be utilized by the handler to
     abandon outbound payments that have failed for any reason.

2. Consistency in Custom Message Handling:
   - Updated `handle_custom_message` to accept optional custom data.
     for consistency.
   - Note: `custom_data` will remain unused in this PR.
  • Loading branch information
shaavan committed Jul 9, 2024
1 parent 7f82cde commit fbe9dfa
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 25 deletions.
17 changes: 12 additions & 5 deletions fuzz/src/onion_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use bitcoin::secp256k1::ecdsa::RecoverableSignature;
use bitcoin::secp256k1::schnorr;
use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};

use lightning::blinded_path::message::{MessageContext, OffersContext};
use lightning::blinded_path::{BlindedPath, EmptyNodeIdLookUp};
use lightning::ln::features::InitFeatures;
use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler};
Expand Down Expand Up @@ -104,7 +105,7 @@ struct TestOffersMessageHandler {}

impl OffersMessageHandler for TestOffersMessageHandler {
fn handle_message(
&self, _message: OffersMessage, _responder: Option<Responder>,
&self, _message: OffersMessage, _context: OffersContext, _responder: Option<Responder>,
) -> ResponseInstruction<OffersMessage> {
ResponseInstruction::NoResponse
}
Expand Down Expand Up @@ -152,7 +153,8 @@ struct TestCustomMessageHandler {}
impl CustomOnionMessageHandler for TestCustomMessageHandler {
type CustomMessage = TestCustomMessage;
fn handle_custom_message(
&self, message: Self::CustomMessage, responder: Option<Responder>,
&self, message: Self::CustomMessage, _context: Option<Vec<u8>>,
responder: Option<Responder>,
) -> ResponseInstruction<Self::CustomMessage> {
match responder {
Some(responder) => responder.respond(message),
Expand Down Expand Up @@ -342,9 +344,14 @@ mod tests {
super::do_test(&<Vec<u8>>::from_hex(one_hop_om).unwrap(), &logger);
{
let log_entries = logger.lines.lock().unwrap();
assert_eq!(log_entries.get(&("lightning::onion_message::messenger".to_string(),
"Received an onion message with path_id None and a reply_path: Custom(TestCustomMessage)"
.to_string())), Some(&1));
assert_eq!(
log_entries.get(&(
"lightning::onion_message::messenger".to_string(),
"Received an onion message with a reply_path: Custom(TestCustomMessage)"
.to_string()
)),
Some(&1)
);
assert_eq!(log_entries.get(&("lightning::onion_message::messenger".to_string(),
"Constructing onion message when responding with Custom Message to an onion message: TestCustomMessage".to_string())), Some(&1));
assert_eq!(log_entries.get(&("lightning::onion_message::messenger".to_string(),
Expand Down
30 changes: 24 additions & 6 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use bitcoin::secp256k1::{SecretKey,PublicKey};
use bitcoin::secp256k1::Secp256k1;
use bitcoin::{secp256k1, Sequence};

use crate::blinded_path::message::OffersContext;
use crate::blinded_path::{BlindedPath, NodeIdLookUp};
use crate::blinded_path::message::ForwardNode;
use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, ReceiveTlvs};
Expand Down Expand Up @@ -10253,10 +10254,17 @@ where
R::Target: Router,
L::Target: Logger,
{
fn handle_message(&self, message: OffersMessage, responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
fn handle_message(&self, message: OffersMessage, context: OffersContext, responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
let secp_ctx = &self.secp_ctx;
let expanded_key = &self.inbound_payment_key;

let abandon_if_payment = |context| {
match context {
OffersContext::OutboundPayment { payment_id } => self.abandon_payment(payment_id),
_ => {},
}
};

match message {
OffersMessage::InvoiceRequest(invoice_request) => {
let responder = match responder {
Expand Down Expand Up @@ -10369,12 +10377,21 @@ where
};

match result {
Ok(()) => ResponseInstruction::NoResponse,
Err(e) => match responder {
Some(responder) => responder.respond(OffersMessage::InvoiceError(e)),
Ok(_) => ResponseInstruction::NoResponse,
Err(err) => match responder {
Some(responder) => {
abandon_if_payment(context);
responder.respond(OffersMessage::InvoiceError(err))
},
None => {
log_trace!(self.logger, "No reply path for sending invoice error: {:?}", e);
ResponseInstruction::NoResponse
abandon_if_payment(context);
log_trace!(
self.logger,
"An error response was generated, but there is no reply_path specified \
for sending the response. Error: {}",
err
);
return ResponseInstruction::NoResponse;
},
},
}
Expand All @@ -10391,6 +10408,7 @@ where
}
},
OffersMessage::InvoiceError(invoice_error) => {
abandon_if_payment(context);
log_trace!(self.logger, "Received invoice_error: {}", invoice_error);
ResponseInstruction::NoResponse
},
Expand Down
5 changes: 3 additions & 2 deletions lightning/src/ln/peer_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use bitcoin::blockdata::constants::ChainHash;
use bitcoin::secp256k1::{self, Secp256k1, SecretKey, PublicKey};

use crate::blinded_path::message::OffersContext;
use crate::sign::{NodeSigner, Recipient};
use crate::events::{MessageSendEvent, MessageSendEventsProvider};
use crate::ln::types::ChannelId;
Expand Down Expand Up @@ -145,7 +146,7 @@ impl OnionMessageHandler for IgnoringMessageHandler {
}

impl OffersMessageHandler for IgnoringMessageHandler {
fn handle_message(&self, _message: OffersMessage, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
fn handle_message(&self, _message: OffersMessage, _context: OffersContext, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
ResponseInstruction::NoResponse
}
}
Expand All @@ -159,7 +160,7 @@ impl AsyncPaymentsMessageHandler for IgnoringMessageHandler {
}
impl CustomOnionMessageHandler for IgnoringMessageHandler {
type CustomMessage = Infallible;
fn handle_custom_message(&self, _message: Self::CustomMessage, _responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
fn handle_custom_message(&self, _message: Self::CustomMessage, _context: Option<Vec<u8>>, _responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
// Since we always return `None` in the read the handle method should never be called.
unreachable!();
}
Expand Down
12 changes: 6 additions & 6 deletions lightning/src/onion_message/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//! Onion message testing and test utilities live here.
use crate::blinded_path::{BlindedPath, EmptyNodeIdLookUp};
use crate::blinded_path::message::ForwardNode;
use crate::blinded_path::message::{ForwardNode, OffersContext};
use crate::events::{Event, EventsProvider};
use crate::ln::features::{ChannelFeatures, InitFeatures};
use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
Expand Down Expand Up @@ -76,7 +76,7 @@ impl Drop for MessengerNode {
struct TestOffersMessageHandler {}

impl OffersMessageHandler for TestOffersMessageHandler {
fn handle_message(&self, _message: OffersMessage, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
fn handle_message(&self, _message: OffersMessage, _context: OffersContext, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
ResponseInstruction::NoResponse
}
}
Expand Down Expand Up @@ -174,7 +174,7 @@ impl Drop for TestCustomMessageHandler {

impl CustomOnionMessageHandler for TestCustomMessageHandler {
type CustomMessage = TestCustomMessage;
fn handle_custom_message(&self, msg: Self::CustomMessage, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
fn handle_custom_message(&self, msg: Self::CustomMessage, _context: Option<Vec<u8>>, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
let expectation = self.get_next_expectation();
assert_eq!(msg, expectation.expect);

Expand Down Expand Up @@ -437,7 +437,7 @@ fn async_response_over_one_blinded_hop() {

// 5. Expect Alice to receive the message and create a response instruction for it.
alice.custom_message_handler.expect_message(message.clone());
let response_instruction = nodes[0].custom_message_handler.handle_custom_message(message, responder);
let response_instruction = nodes[0].custom_message_handler.handle_custom_message(message, None, responder);

// 6. Simulate Alice asynchronously responding back to Bob with a response.
assert_eq!(
Expand Down Expand Up @@ -470,7 +470,7 @@ fn async_response_with_reply_path_succeeds() {
// Alice asynchronously responds to Bob, expecting a response back from him.
let responder = Responder::new(reply_path);
alice.custom_message_handler.expect_message_and_response(message.clone());
let response_instruction = alice.custom_message_handler.handle_custom_message(message, Some(responder));
let response_instruction = alice.custom_message_handler.handle_custom_message(message, None, Some(responder));

assert_eq!(
alice.messenger.handle_onion_message_response(response_instruction),
Expand Down Expand Up @@ -508,7 +508,7 @@ fn async_response_with_reply_path_fails() {
disconnect_peers(alice, bob);
let responder = Responder::new(reply_path);
alice.custom_message_handler.expect_message_and_response(message.clone());
let response_instruction = alice.custom_message_handler.handle_custom_message(message, Some(responder));
let response_instruction = alice.custom_message_handler.handle_custom_message(message, None, Some(responder));

assert_eq!(
alice.messenger.handle_onion_message_response(response_instruction),
Expand Down
26 changes: 21 additions & 5 deletions lightning/src/onion_message/messenger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};

use crate::blinded_path::{BlindedPath, IntroductionNode, NextMessageHop, NodeIdLookUp};
use crate::blinded_path::message::{advance_path_by_one, ForwardNode, ForwardTlvs, ReceiveTlvs, MessageContext};
use crate::blinded_path::message::{advance_path_by_one, ForwardNode, ForwardTlvs, MessageContext, OffersContext, ReceiveTlvs};
use crate::blinded_path::utils;
use crate::events::{Event, EventHandler, EventsProvider};
use crate::sign::{EntropySource, NodeSigner, Recipient};
Expand Down Expand Up @@ -768,7 +768,7 @@ pub trait CustomOnionMessageHandler {
/// Called with the custom message that was received, returning a response to send, if any.
///
/// The returned [`Self::CustomMessage`], if any, is enqueued to be sent by [`OnionMessenger`].
fn handle_custom_message(&self, message: Self::CustomMessage, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage>;
fn handle_custom_message(&self, message: Self::CustomMessage, context: Option<Vec<u8>>, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage>;

/// Read a custom message of type `message_type` from `buffer`, returning `Ok(None)` if the
/// message type is unknown.
Expand Down Expand Up @@ -1446,7 +1446,7 @@ where
fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage) {
let logger = WithContext::from(&self.logger, Some(*peer_node_id), None, None);
match self.peel_onion_message(msg) {
Ok(PeeledOnion::Receive(message, _context, reply_path)) => {
Ok(PeeledOnion::Receive(message, context, reply_path)) => {
log_trace!(
logger,
"Received an onion message with {} reply_path: {:?}",
Expand All @@ -1455,7 +1455,15 @@ where
let responder = reply_path.map(Responder::new);
match message {
ParsedOnionMessageContents::Offers(msg) => {
let response_instructions = self.offers_handler.handle_message(msg, responder);
let context = match context {
None => OffersContext::Unknown {},
Some(MessageContext::Offers(context)) => context,
Some(MessageContext::Custom(_)) => {
debug_assert!(false, "Shouldn't have triggered this case.");
return
}
};
let response_instructions = self.offers_handler.handle_message(msg, context, responder);
let _ = self.handle_onion_message_response(response_instructions);
},
#[cfg(async_payments)]
Expand All @@ -1470,7 +1478,15 @@ where
self.async_payments_handler.release_held_htlc(msg);
},
ParsedOnionMessageContents::Custom(msg) => {
let response_instructions = self.custom_handler.handle_custom_message(msg, responder);
let context = match context {
None => None,
Some(MessageContext::Custom(data)) => Some(data),
Some(MessageContext::Offers(_)) => {
debug_assert!(false, "Shouldn't have triggered this case.");
return
}
};
let response_instructions = self.custom_handler.handle_custom_message(msg, context, responder);
let _ = self.handle_onion_message_response(response_instructions);
},
}
Expand Down
3 changes: 2 additions & 1 deletion lightning/src/onion_message/offers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
//! Message handling for BOLT 12 Offers.
use core::fmt;
use crate::blinded_path::message::OffersContext;
use crate::io::{self, Read};
use crate::ln::msgs::DecodeError;
use crate::offers::invoice_error::InvoiceError;
Expand Down Expand Up @@ -44,7 +45,7 @@ pub trait OffersMessageHandler {
/// The returned [`OffersMessage`], if any, is enqueued to be sent by [`OnionMessenger`].
///
/// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger
fn handle_message(&self, message: OffersMessage, responder: Option<Responder>) -> ResponseInstruction<OffersMessage>;
fn handle_message(&self, message: OffersMessage, context: OffersContext, responder: Option<Responder>) -> ResponseInstruction<OffersMessage>;

/// Releases any [`OffersMessage`]s that need to be sent.
///
Expand Down

0 comments on commit fbe9dfa

Please sign in to comment.