Merge pull request #3263 from TheBlueMatt/2024-08-bindings-om

Remove message type bound on `ResponseInstruction`
This commit is contained in:
Matt Corallo 2024-08-23 03:04:19 +00:00 committed by GitHub
commit 49dfa5a496
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 274 additions and 307 deletions

View file

@ -16,8 +16,8 @@ use lightning::onion_message::async_payments::{
AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc,
};
use lightning::onion_message::messenger::{
CustomOnionMessageHandler, Destination, MessageRouter, OnionMessagePath, OnionMessenger,
PendingOnionMessage, Responder, ResponseInstruction,
CustomOnionMessageHandler, Destination, MessageRouter, MessageSendInstructions,
OnionMessagePath, OnionMessenger, Responder, ResponseInstruction,
};
use lightning::onion_message::offers::{OffersMessage, OffersMessageHandler};
use lightning::onion_message::packet::OnionMessageContents;
@ -109,8 +109,8 @@ impl OffersMessageHandler for TestOffersMessageHandler {
fn handle_message(
&self, _message: OffersMessage, _context: Option<OffersContext>,
_responder: Option<Responder>,
) -> ResponseInstruction<OffersMessage> {
ResponseInstruction::NoResponse
) -> Option<(OffersMessage, ResponseInstruction)> {
None
}
}
@ -119,13 +119,15 @@ struct TestAsyncPaymentsMessageHandler {}
impl AsyncPaymentsMessageHandler for TestAsyncPaymentsMessageHandler {
fn held_htlc_available(
&self, message: HeldHtlcAvailable, responder: Option<Responder>,
) -> ResponseInstruction<ReleaseHeldHtlc> {
) -> Option<(ReleaseHeldHtlc, ResponseInstruction)> {
let responder = match responder {
Some(resp) => resp,
None => return ResponseInstruction::NoResponse,
None => return None,
};
responder
.respond(ReleaseHeldHtlc { payment_release_secret: message.payment_release_secret })
Some((
ReleaseHeldHtlc { payment_release_secret: message.payment_release_secret },
responder.respond(),
))
}
fn release_held_htlc(&self, _message: ReleaseHeldHtlc) {}
}
@ -158,10 +160,10 @@ impl CustomOnionMessageHandler for TestCustomMessageHandler {
fn handle_custom_message(
&self, message: Self::CustomMessage, _context: Option<Vec<u8>>,
responder: Option<Responder>,
) -> ResponseInstruction<Self::CustomMessage> {
) -> Option<(Self::CustomMessage, ResponseInstruction)> {
match responder {
Some(responder) => responder.respond(message),
None => ResponseInstruction::NoResponse,
Some(responder) => Some((message, responder.respond())),
None => None,
}
}
fn read_custom_message<R: io::Read>(
@ -171,7 +173,7 @@ impl CustomOnionMessageHandler for TestCustomMessageHandler {
buffer.read_to_limit(&mut buf, u64::MAX)?;
return Ok(Some(TestCustomMessage {}));
}
fn release_pending_custom_messages(&self) -> Vec<PendingOnionMessage<Self::CustomMessage>> {
fn release_pending_custom_messages(&self) -> Vec<(TestCustomMessage, MessageSendInstructions)> {
vec![]
}
}

View file

@ -71,7 +71,7 @@ use crate::offers::parse::Bolt12SemanticError;
use crate::offers::refund::{Refund, RefundBuilder};
use crate::offers::signer;
use crate::onion_message::async_payments::{AsyncPaymentsMessage, HeldHtlcAvailable, ReleaseHeldHtlc, AsyncPaymentsMessageHandler};
use crate::onion_message::messenger::{new_pending_onion_message, Destination, MessageRouter, PendingOnionMessage, Responder, ResponseInstruction};
use crate::onion_message::messenger::{Destination, MessageRouter, Responder, ResponseInstruction, MessageSendInstructions};
use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider};
use crate::sign::ecdsa::EcdsaChannelSigner;
@ -2277,9 +2277,9 @@ where
needs_persist_flag: AtomicBool,
#[cfg(not(any(test, feature = "_test_utils")))]
pending_offers_messages: Mutex<Vec<PendingOnionMessage<OffersMessage>>>,
pending_offers_messages: Mutex<Vec<(OffersMessage, MessageSendInstructions)>>,
#[cfg(any(test, feature = "_test_utils"))]
pub(crate) pending_offers_messages: Mutex<Vec<PendingOnionMessage<OffersMessage>>>,
pub(crate) pending_offers_messages: Mutex<Vec<(OffersMessage, MessageSendInstructions)>>,
/// Tracks the message events that are to be broadcasted when we are connected to some peer.
pending_broadcast_messages: Mutex<Vec<MessageSendEvent>>,
@ -9068,21 +9068,21 @@ where
.flat_map(|reply_path| offer.paths().iter().map(move |path| (path, reply_path)))
.take(OFFERS_MESSAGE_REQUEST_LIMIT)
.for_each(|(path, reply_path)| {
let message = new_pending_onion_message(
OffersMessage::InvoiceRequest(invoice_request.clone()),
Destination::BlindedPath(path.clone()),
Some(reply_path.clone()),
);
pending_offers_messages.push(message);
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
destination: Destination::BlindedPath(path.clone()),
reply_path: reply_path.clone(),
};
let message = OffersMessage::InvoiceRequest(invoice_request.clone());
pending_offers_messages.push((message, instructions));
});
} else if let Some(signing_pubkey) = offer.signing_pubkey() {
for reply_path in reply_paths {
let message = new_pending_onion_message(
OffersMessage::InvoiceRequest(invoice_request.clone()),
Destination::Node(signing_pubkey),
Some(reply_path),
);
pending_offers_messages.push(message);
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
destination: Destination::Node(signing_pubkey),
reply_path,
};
let message = OffersMessage::InvoiceRequest(invoice_request.clone());
pending_offers_messages.push((message, instructions));
}
} else {
debug_assert!(false);
@ -9162,12 +9162,12 @@ where
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
if refund.paths().is_empty() {
for reply_path in reply_paths {
let message = new_pending_onion_message(
OffersMessage::Invoice(invoice.clone()),
Destination::Node(refund.payer_id()),
Some(reply_path),
);
pending_offers_messages.push(message);
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
destination: Destination::Node(refund.payer_id()),
reply_path,
};
let message = OffersMessage::Invoice(invoice.clone());
pending_offers_messages.push((message, instructions));
}
} else {
reply_paths
@ -9175,12 +9175,12 @@ where
.flat_map(|reply_path| refund.paths().iter().map(move |path| (path, reply_path)))
.take(OFFERS_MESSAGE_REQUEST_LIMIT)
.for_each(|(path, reply_path)| {
let message = new_pending_onion_message(
OffersMessage::Invoice(invoice.clone()),
Destination::BlindedPath(path.clone()),
Some(reply_path.clone()),
);
pending_offers_messages.push(message);
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
destination: Destination::BlindedPath(path.clone()),
reply_path: reply_path.clone(),
};
let message = OffersMessage::Invoice(invoice.clone());
pending_offers_messages.push((message, instructions));
});
}
@ -10749,7 +10749,7 @@ where
{
fn handle_message(
&self, message: OffersMessage, context: Option<OffersContext>, responder: Option<Responder>,
) -> ResponseInstruction<OffersMessage> {
) -> Option<(OffersMessage, ResponseInstruction)> {
let secp_ctx = &self.secp_ctx;
let expanded_key = &self.inbound_payment_key;
@ -10757,13 +10757,13 @@ where
OffersMessage::InvoiceRequest(invoice_request) => {
let responder = match responder {
Some(responder) => responder,
None => return ResponseInstruction::NoResponse,
None => return None,
};
let nonce = match context {
None if invoice_request.metadata().is_some() => None,
Some(OffersContext::InvoiceRequest { nonce }) => Some(nonce),
_ => return ResponseInstruction::NoResponse,
_ => return None,
};
let invoice_request = match nonce {
@ -10771,11 +10771,11 @@ where
nonce, expanded_key, secp_ctx,
) {
Ok(invoice_request) => invoice_request,
Err(()) => return ResponseInstruction::NoResponse,
Err(()) => return None,
},
None => match invoice_request.verify_using_metadata(expanded_key, secp_ctx) {
Ok(invoice_request) => invoice_request,
Err(()) => return ResponseInstruction::NoResponse,
Err(()) => return None,
},
};
@ -10783,7 +10783,7 @@ where
&invoice_request.inner
) {
Ok(amount_msats) => amount_msats,
Err(error) => return responder.respond(OffersMessage::InvoiceError(error.into())),
Err(error) => return Some((OffersMessage::InvoiceError(error.into()), responder.respond())),
};
let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32;
@ -10793,7 +10793,7 @@ where
Ok((payment_hash, payment_secret)) => (payment_hash, payment_secret),
Err(()) => {
let error = Bolt12SemanticError::InvalidAmount;
return responder.respond(OffersMessage::InvoiceError(error.into()));
return Some((OffersMessage::InvoiceError(error.into()), responder.respond()));
},
};
@ -10807,7 +10807,7 @@ where
Ok(payment_paths) => payment_paths,
Err(()) => {
let error = Bolt12SemanticError::MissingPaths;
return responder.respond(OffersMessage::InvoiceError(error.into()));
return Some((OffersMessage::InvoiceError(error.into()), responder.respond()));
},
};
@ -10852,14 +10852,14 @@ where
};
match response {
Ok(invoice) => responder.respond(OffersMessage::Invoice(invoice)),
Err(error) => responder.respond(OffersMessage::InvoiceError(error.into())),
Ok(invoice) => Some((OffersMessage::Invoice(invoice), responder.respond())),
Err(error) => Some((OffersMessage::InvoiceError(error.into()), responder.respond())),
}
},
OffersMessage::Invoice(invoice) => {
let payment_id = match self.verify_bolt12_invoice(&invoice, context.as_ref()) {
Ok(payment_id) => payment_id,
Err(()) => return ResponseInstruction::NoResponse,
Err(()) => return None,
};
let logger = WithContext::from(
@ -10871,7 +10871,7 @@ where
payment_id, invoice, context, responder,
};
self.pending_events.lock().unwrap().push_back((event, None));
return ResponseInstruction::NoResponse;
return None;
}
let error = match self.send_payment_for_verified_bolt12_invoice(
@ -10890,14 +10890,14 @@ where
},
Err(Bolt12PaymentError::UnexpectedInvoice)
| Err(Bolt12PaymentError::DuplicateInvoice)
| Ok(()) => return ResponseInstruction::NoResponse,
| Ok(()) => return None,
};
match responder {
Some(responder) => responder.respond(OffersMessage::InvoiceError(error)),
Some(responder) => Some((OffersMessage::InvoiceError(error), responder.respond())),
None => {
log_trace!(logger, "No reply path to send error: {:?}", error);
ResponseInstruction::NoResponse
None
},
}
},
@ -10905,11 +10905,11 @@ where
OffersMessage::StaticInvoice(_invoice) => {
match responder {
Some(responder) => {
responder.respond(OffersMessage::InvoiceError(
InvoiceError::from_string("Static invoices not yet supported".to_string())
))
return Some((OffersMessage::InvoiceError(
InvoiceError::from_string("Static invoices not yet supported".to_string())
), responder.respond()));
},
None => return ResponseInstruction::NoResponse,
None => return None,
}
},
OffersMessage::InvoiceError(invoice_error) => {
@ -10932,12 +10932,12 @@ where
_ => {},
}
ResponseInstruction::NoResponse
None
},
}
}
fn release_pending_messages(&self) -> Vec<PendingOnionMessage<OffersMessage>> {
fn release_pending_messages(&self) -> Vec<(OffersMessage, MessageSendInstructions)> {
core::mem::take(&mut self.pending_offers_messages.lock().unwrap())
}
}
@ -10956,13 +10956,13 @@ where
{
fn held_htlc_available(
&self, _message: HeldHtlcAvailable, _responder: Option<Responder>
) -> ResponseInstruction<ReleaseHeldHtlc> {
ResponseInstruction::NoResponse
) -> Option<(ReleaseHeldHtlc, ResponseInstruction)> {
None
}
fn release_held_htlc(&self, _message: ReleaseHeldHtlc) {}
fn release_pending_messages(&self) -> Vec<PendingOnionMessage<AsyncPaymentsMessage>> {
fn release_pending_messages(&self) -> Vec<(AsyncPaymentsMessage, MessageSendInstructions)> {
Vec::new()
}
}

View file

@ -59,7 +59,7 @@ use crate::offers::invoice_error::InvoiceError;
use crate::offers::invoice_request::{InvoiceRequest, InvoiceRequestFields};
use crate::offers::nonce::Nonce;
use crate::offers::parse::Bolt12SemanticError;
use crate::onion_message::messenger::{Destination, PeeledOnion, new_pending_onion_message};
use crate::onion_message::messenger::{Destination, PeeledOnion, MessageSendInstructions};
use crate::onion_message::offers::OffersMessage;
use crate::onion_message::packet::ParsedOnionMessageContents;
use crate::routing::gossip::{NodeAlias, NodeId};
@ -1313,13 +1313,10 @@ fn fails_authentication_when_handling_invoice_request() {
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
connect_peers(david, alice);
#[cfg(not(c_bindings))] {
david.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().destination =
Destination::Node(alice_id);
}
#[cfg(c_bindings)] {
david.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 =
Destination::Node(alice_id);
match &mut david.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } =>
*destination = Destination::Node(alice_id),
_ => panic!(),
}
let onion_message = david.onion_messenger.next_onion_message_for_peer(alice_id).unwrap();
@ -1341,13 +1338,10 @@ fn fails_authentication_when_handling_invoice_request() {
.unwrap();
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
#[cfg(not(c_bindings))] {
david.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().destination =
Destination::BlindedPath(invalid_path);
}
#[cfg(c_bindings)] {
david.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 =
Destination::BlindedPath(invalid_path);
match &mut david.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } =>
*destination = Destination::BlindedPath(invalid_path),
_ => panic!(),
}
connect_peers(david, bob);
@ -1427,11 +1421,9 @@ fn fails_authentication_when_handling_invoice_for_offer() {
let mut pending_offers_messages = david.node.pending_offers_messages.lock().unwrap();
let pending_invoice_request = pending_offers_messages.pop().unwrap();
pending_offers_messages.clear();
#[cfg(not(c_bindings))] {
pending_invoice_request.reply_path
}
#[cfg(c_bindings)] {
pending_invoice_request.2
match pending_invoice_request.1 {
MessageSendInstructions::WithSpecifiedReplyPath { reply_path, .. } => reply_path,
_ => panic!(),
}
};
@ -1445,11 +1437,10 @@ fn fails_authentication_when_handling_invoice_for_offer() {
{
let mut pending_offers_messages = david.node.pending_offers_messages.lock().unwrap();
let mut pending_invoice_request = pending_offers_messages.first_mut().unwrap();
#[cfg(not(c_bindings))] {
pending_invoice_request.reply_path = invalid_reply_path;
}
#[cfg(c_bindings)] {
pending_invoice_request.2 = invalid_reply_path;
match &mut pending_invoice_request.1 {
MessageSendInstructions::WithSpecifiedReplyPath { reply_path, .. } =>
*reply_path = invalid_reply_path,
_ => panic!(),
}
}
@ -1531,13 +1522,10 @@ fn fails_authentication_when_handling_invoice_for_refund() {
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
connect_peers(david, alice);
#[cfg(not(c_bindings))] {
alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().destination =
Destination::Node(david_id);
}
#[cfg(c_bindings)] {
alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 =
Destination::Node(david_id);
match &mut alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } =>
*destination = Destination::Node(david_id),
_ => panic!(),
}
let onion_message = alice.onion_messenger.next_onion_message_for_peer(david_id).unwrap();
@ -1565,13 +1553,10 @@ fn fails_authentication_when_handling_invoice_for_refund() {
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
#[cfg(not(c_bindings))] {
alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().destination =
Destination::BlindedPath(invalid_path);
}
#[cfg(c_bindings)] {
alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 =
Destination::BlindedPath(invalid_path);
match &mut alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } =>
*destination = Destination::BlindedPath(invalid_path),
_ => panic!(),
}
connect_peers(alice, charlie);
@ -2155,10 +2140,11 @@ fn fails_paying_invoice_with_unknown_required_features() {
.build_and_sign(&secp_ctx).unwrap();
// Enqueue an onion message containing the new invoice.
let pending_message = new_pending_onion_message(
OffersMessage::Invoice(invoice), Destination::BlindedPath(reply_path), None
);
alice.node.pending_offers_messages.lock().unwrap().push(pending_message);
let instructions = MessageSendInstructions::WithoutReplyPath {
destination: Destination::BlindedPath(reply_path),
};
let message = OffersMessage::Invoice(invoice);
alice.node.pending_offers_messages.lock().unwrap().push((message, instructions));
let onion_message = alice.onion_messenger.next_onion_message_for_peer(charlie_id).unwrap();
charlie.onion_messenger.handle_onion_message(&alice_id, &onion_message);

View file

@ -30,7 +30,7 @@ use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor, NextNoiseStep, Mes
use crate::ln::wire;
use crate::ln::wire::{Encode, Type};
use crate::onion_message::async_payments::{AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc};
use crate::onion_message::messenger::{CustomOnionMessageHandler, PendingOnionMessage, Responder, ResponseInstruction};
use crate::onion_message::messenger::{CustomOnionMessageHandler, Responder, ResponseInstruction, MessageSendInstructions};
use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
use crate::onion_message::packet::OnionMessageContents;
use crate::routing::gossip::{NodeId, NodeAlias};
@ -142,28 +142,28 @@ impl OnionMessageHandler for IgnoringMessageHandler {
}
impl OffersMessageHandler for IgnoringMessageHandler {
fn handle_message(&self, _message: OffersMessage, _context: Option<OffersContext>, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
ResponseInstruction::NoResponse
fn handle_message(&self, _message: OffersMessage, _context: Option<OffersContext>, _responder: Option<Responder>) -> Option<(OffersMessage, ResponseInstruction)> {
None
}
}
impl AsyncPaymentsMessageHandler for IgnoringMessageHandler {
fn held_htlc_available(
&self, _message: HeldHtlcAvailable, _responder: Option<Responder>,
) -> ResponseInstruction<ReleaseHeldHtlc> {
ResponseInstruction::NoResponse
) -> Option<(ReleaseHeldHtlc, ResponseInstruction)> {
None
}
fn release_held_htlc(&self, _message: ReleaseHeldHtlc) {}
}
impl CustomOnionMessageHandler for IgnoringMessageHandler {
type CustomMessage = Infallible;
fn handle_custom_message(&self, _message: Self::CustomMessage, _context: Option<Vec<u8>>, _responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
fn handle_custom_message(&self, _message: Self::CustomMessage, _context: Option<Vec<u8>>, _responder: Option<Responder>) -> Option<(Infallible, ResponseInstruction)> {
// Since we always return `None` in the read the handle method should never be called.
unreachable!();
}
fn read_custom_message<R: io::Read>(&self, _msg_type: u64, _buffer: &mut R) -> Result<Option<Infallible>, msgs::DecodeError> where Self: Sized {
Ok(None)
}
fn release_pending_custom_messages(&self) -> Vec<PendingOnionMessage<Infallible>> {
fn release_pending_custom_messages(&self) -> Vec<(Infallible, MessageSendInstructions)> {
vec![]
}
}

View file

@ -11,9 +11,7 @@
use crate::io;
use crate::ln::msgs::DecodeError;
#[cfg(not(c_bindings))]
use crate::onion_message::messenger::PendingOnionMessage;
use crate::onion_message::messenger::{Responder, ResponseInstruction};
use crate::onion_message::messenger::{MessageSendInstructions, Responder, ResponseInstruction};
use crate::onion_message::packet::OnionMessageContents;
use crate::prelude::*;
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
@ -30,7 +28,7 @@ pub trait AsyncPaymentsMessageHandler {
/// the held funds.
fn held_htlc_available(
&self, message: HeldHtlcAvailable, responder: Option<Responder>,
) -> ResponseInstruction<ReleaseHeldHtlc>;
) -> Option<(ReleaseHeldHtlc, ResponseInstruction)>;
/// Handle a [`ReleaseHeldHtlc`] message. If authentication of the message succeeds, an HTLC
/// should be released to the corresponding payee.
@ -40,23 +38,7 @@ pub trait AsyncPaymentsMessageHandler {
///
/// Typically, this is used for messages initiating an async payment flow rather than in response
/// to another message.
#[cfg(not(c_bindings))]
fn release_pending_messages(&self) -> Vec<PendingOnionMessage<AsyncPaymentsMessage>> {
vec![]
}
/// Release any [`AsyncPaymentsMessage`]s that need to be sent.
///
/// Typically, this is used for messages initiating a payment flow rather than in response to
/// another message.
#[cfg(c_bindings)]
fn release_pending_messages(
&self,
) -> Vec<(
AsyncPaymentsMessage,
crate::onion_message::messenger::Destination,
Option<crate::blinded_path::message::BlindedMessagePath>,
)> {
fn release_pending_messages(&self) -> Vec<(AsyncPaymentsMessage, MessageSendInstructions)> {
vec![]
}
}

View file

@ -20,7 +20,7 @@ use crate::sign::{NodeSigner, Recipient};
use crate::util::ser::{FixedLengthReader, LengthReadable, Writeable, Writer};
use crate::util::test_utils;
use super::async_payments::{AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc};
use super::messenger::{CustomOnionMessageHandler, DefaultMessageRouter, Destination, OnionMessagePath, OnionMessenger, PendingOnionMessage, Responder, ResponseInstruction, SendError, SendSuccess};
use super::messenger::{CustomOnionMessageHandler, DefaultMessageRouter, Destination, OnionMessagePath, OnionMessenger, Responder, ResponseInstruction, MessageSendInstructions, SendError, SendSuccess};
use super::offers::{OffersMessage, OffersMessageHandler};
use super::packet::{OnionMessageContents, Packet};
@ -74,8 +74,8 @@ impl Drop for MessengerNode {
struct TestOffersMessageHandler {}
impl OffersMessageHandler for TestOffersMessageHandler {
fn handle_message(&self, _message: OffersMessage, _context: Option<OffersContext>, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
ResponseInstruction::NoResponse
fn handle_message(&self, _message: OffersMessage, _context: Option<OffersContext>, _responder: Option<Responder>) -> Option<(OffersMessage, ResponseInstruction)> {
None
}
}
@ -84,8 +84,8 @@ struct TestAsyncPaymentsMessageHandler {}
impl AsyncPaymentsMessageHandler for TestAsyncPaymentsMessageHandler {
fn held_htlc_available(
&self, _message: HeldHtlcAvailable, _responder: Option<Responder>,
) -> ResponseInstruction<ReleaseHeldHtlc> {
ResponseInstruction::NoResponse
) -> Option<(ReleaseHeldHtlc, ResponseInstruction)> {
None
}
fn release_held_htlc(&self, _message: ReleaseHeldHtlc) {}
}
@ -170,7 +170,7 @@ impl Drop for TestCustomMessageHandler {
impl CustomOnionMessageHandler for TestCustomMessageHandler {
type CustomMessage = TestCustomMessage;
fn handle_custom_message(&self, msg: Self::CustomMessage, context: Option<Vec<u8>>, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
fn handle_custom_message(&self, msg: Self::CustomMessage, context: Option<Vec<u8>>, responder: Option<Responder>) -> Option<(Self::CustomMessage, ResponseInstruction)> {
let expectation = self.get_next_expectation();
assert_eq!(msg, expectation.expect);
@ -186,10 +186,10 @@ impl CustomOnionMessageHandler for TestCustomMessageHandler {
match responder {
Some(responder) if expectation.include_reply_path => {
responder.respond_with_reply_path(response, MessageContext::Custom(context.unwrap_or_else(Vec::new)))
Some((response, responder.respond_with_reply_path(MessageContext::Custom(context.unwrap_or_else(Vec::new)))))
},
Some(responder) => responder.respond(response),
None => ResponseInstruction::NoResponse,
Some(responder) => Some((response, responder.respond())),
None => None
}
}
fn read_custom_message<R: io::Read>(&self, message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, DecodeError> where Self: Sized {
@ -207,7 +207,7 @@ impl CustomOnionMessageHandler for TestCustomMessageHandler {
_ => Ok(None),
}
}
fn release_pending_custom_messages(&self) -> Vec<PendingOnionMessage<Self::CustomMessage>> {
fn release_pending_custom_messages(&self) -> Vec<(Self::CustomMessage, MessageSendInstructions)> {
vec![]
}
}
@ -341,7 +341,8 @@ fn one_unblinded_hop() {
let test_msg = TestCustomMessage::Pong;
let destination = Destination::Node(nodes[1].node_id);
nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap();
nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
pass_along_path(&nodes);
}
@ -371,7 +372,8 @@ fn one_blinded_hop() {
let context = MessageContext::Custom(Vec::new());
let blinded_path = BlindedMessagePath::new(&[], nodes[1].node_id, context, &*nodes[1].entropy_source, &secp_ctx).unwrap();
let destination = Destination::BlindedPath(blinded_path);
nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap();
nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
pass_along_path(&nodes);
}
@ -409,8 +411,9 @@ fn three_blinded_hops() {
let context = MessageContext::Custom(Vec::new());
let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[3].node_id, context, &*nodes[3].entropy_source, &secp_ctx).unwrap();
let destination = Destination::BlindedPath(blinded_path);
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap();
nodes[3].custom_message_handler.expect_message(TestCustomMessage::Pong);
pass_along_path(&nodes);
}
@ -440,9 +443,10 @@ fn async_response_over_one_blinded_hop() {
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.
let (msg, instructions) = response_instruction.unwrap();
assert_eq!(
nodes[0].messenger.handle_onion_message_response(response_instruction),
Ok(Some(SendSuccess::Buffered)),
nodes[0].messenger.handle_onion_message_response(msg, instructions),
Ok(SendSuccess::Buffered),
);
bob.custom_message_handler.expect_message(TestCustomMessage::Pong);
@ -473,9 +477,10 @@ fn async_response_with_reply_path_succeeds() {
alice.custom_message_handler.expect_message_and_response(message.clone());
let response_instruction = alice.custom_message_handler.handle_custom_message(message, None, Some(responder));
let (msg, instructions) = response_instruction.unwrap();
assert_eq!(
alice.messenger.handle_onion_message_response(response_instruction),
Ok(Some(SendSuccess::Buffered)),
alice.messenger.handle_onion_message_response(msg, instructions),
Ok(SendSuccess::Buffered),
);
// Set Bob's expectation and pass the Onion Message along the path.
@ -512,8 +517,9 @@ fn async_response_with_reply_path_fails() {
alice.custom_message_handler.expect_message_and_response(message.clone());
let response_instruction = alice.custom_message_handler.handle_custom_message(message, None, Some(responder));
let (msg, instructions) = response_instruction.unwrap();
assert_eq!(
alice.messenger.handle_onion_message_response(response_instruction),
alice.messenger.handle_onion_message_response(msg, instructions),
Err(SendError::PathNotFound),
);
}
@ -550,8 +556,9 @@ fn we_are_intro_node() {
let context = MessageContext::Custom(Vec::new());
let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[2].node_id, context, &*nodes[2].entropy_source, &secp_ctx).unwrap();
let destination = Destination::BlindedPath(blinded_path);
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
nodes[0].messenger.send_onion_message(test_msg.clone(), destination, None).unwrap();
nodes[0].messenger.send_onion_message(test_msg.clone(), instructions).unwrap();
nodes[2].custom_message_handler.expect_message(TestCustomMessage::Pong);
pass_along_path(&nodes);
@ -560,7 +567,9 @@ fn we_are_intro_node() {
let context = MessageContext::Custom(Vec::new());
let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[1].node_id, context, &*nodes[1].entropy_source, &secp_ctx).unwrap();
let destination = Destination::BlindedPath(blinded_path);
nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap();
nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
nodes.remove(2);
pass_along_path(&nodes);
@ -578,7 +587,9 @@ fn invalid_blinded_path_error() {
let mut blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[2].node_id, context, &*nodes[2].entropy_source, &secp_ctx).unwrap();
blinded_path.clear_blinded_hops();
let destination = Destination::BlindedPath(blinded_path);
let err = nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap_err();
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
let err = nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap_err();
assert_eq!(err, SendError::TooFewBlindedHops);
}
@ -622,8 +633,9 @@ fn reply_path() {
];
let context = MessageContext::Custom(Vec::new());
let reply_path = BlindedMessagePath::new(&intermediate_nodes, nodes[0].node_id, context, &*nodes[0].entropy_source, &secp_ctx).unwrap();
let instructions = MessageSendInstructions::WithSpecifiedReplyPath { destination, reply_path };
nodes[0].messenger.send_onion_message(test_msg, destination, Some(reply_path)).unwrap();
nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap();
nodes[3].custom_message_handler.expect_message(TestCustomMessage::Ping);
pass_along_path(&nodes);
@ -655,7 +667,9 @@ fn invalid_custom_message_type() {
let test_msg = InvalidCustomMessage {};
let destination = Destination::Node(nodes[1].node_id);
let err = nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap_err();
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
let err = nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap_err();
assert_eq!(err, SendError::InvalidMessage);
}
@ -664,10 +678,12 @@ fn peer_buffer_full() {
let nodes = create_nodes(2);
let test_msg = TestCustomMessage::Ping;
let destination = Destination::Node(nodes[1].node_id);
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
for _ in 0..188 { // Based on MAX_PER_PEER_BUFFER_SIZE in OnionMessenger
nodes[0].messenger.send_onion_message(test_msg.clone(), destination.clone(), None).unwrap();
nodes[0].messenger.send_onion_message(test_msg.clone(), instructions.clone()).unwrap();
}
let err = nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap_err();
let err = nodes[0].messenger.send_onion_message(test_msg, instructions.clone()).unwrap_err();
assert_eq!(err, SendError::BufferFull);
}
@ -707,9 +723,10 @@ fn requests_peer_connection_for_buffered_messages() {
&intermediate_nodes, nodes[2].node_id, context, &*nodes[0].entropy_source, &secp_ctx
).unwrap();
let destination = Destination::BlindedPath(blinded_path);
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
// Buffer an onion message for a connected peer
nodes[0].messenger.send_onion_message(message.clone(), destination.clone(), None).unwrap();
nodes[0].messenger.send_onion_message(message.clone(), instructions.clone()).unwrap();
assert!(release_events(&nodes[0]).is_empty());
assert!(nodes[0].messenger.next_onion_message_for_peer(nodes[1].node_id).is_some());
assert!(nodes[0].messenger.next_onion_message_for_peer(nodes[1].node_id).is_none());
@ -717,7 +734,7 @@ fn requests_peer_connection_for_buffered_messages() {
// Buffer an onion message for a disconnected peer
disconnect_peers(&nodes[0], &nodes[1]);
assert!(nodes[0].messenger.next_onion_message_for_peer(nodes[1].node_id).is_none());
nodes[0].messenger.send_onion_message(message, destination, None).unwrap();
nodes[0].messenger.send_onion_message(message, instructions).unwrap();
// Check that a ConnectionNeeded event for the peer is provided
let events = release_events(&nodes[0]);
@ -746,10 +763,11 @@ fn drops_buffered_messages_waiting_for_peer_connection() {
&intermediate_nodes, nodes[2].node_id, context, &*nodes[0].entropy_source, &secp_ctx
).unwrap();
let destination = Destination::BlindedPath(blinded_path);
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
// Buffer an onion message for a disconnected peer
disconnect_peers(&nodes[0], &nodes[1]);
nodes[0].messenger.send_onion_message(message, destination, None).unwrap();
nodes[0].messenger.send_onion_message(message, instructions).unwrap();
// Release the event so the timer can start ticking
let events = release_events(&nodes[0]);
@ -797,10 +815,11 @@ fn intercept_offline_peer_oms() {
&intermediate_nodes, nodes[2].node_id, context, &*nodes[2].entropy_source, &secp_ctx
).unwrap();
let destination = Destination::BlindedPath(blinded_path);
let instructions = MessageSendInstructions::WithoutReplyPath { destination };
// Disconnect the peers to ensure we intercept the OM.
disconnect_peers(&nodes[1], &nodes[2]);
nodes[0].messenger.send_onion_message(message, destination, None).unwrap();
nodes[0].messenger.send_onion_message(message, instructions).unwrap();
let mut final_node_vec = nodes.split_off(2);
pass_along_path(&nodes);

View file

@ -151,7 +151,7 @@ for OnionMessenger<ES, NS, L, NL, MR, OMH, APH, CMH> where
/// # use lightning::blinded_path::message::{BlindedMessagePath, MessageForwardNode, MessageContext};
/// # use lightning::sign::{EntropySource, KeysManager};
/// # use lightning::ln::peer_handler::IgnoringMessageHandler;
/// # use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath, OnionMessenger};
/// # use lightning::onion_message::messenger::{Destination, MessageRouter, MessageSendInstructions, OnionMessagePath, OnionMessenger};
/// # use lightning::onion_message::packet::OnionMessageContents;
/// # use lightning::util::logger::{Logger, Record};
/// # use lightning::util::ser::{Writeable, Writer};
@ -218,9 +218,9 @@ for OnionMessenger<ES, NS, L, NL, MR, OMH, APH, CMH> where
/// }
/// // Send a custom onion message to a node id.
/// let destination = Destination::Node(destination_node_id);
/// let reply_path = None;
/// let instructions = MessageSendInstructions::WithoutReplyPath { destination };
/// # let message = YourCustomMessage {};
/// onion_messenger.send_onion_message(message, destination, reply_path);
/// onion_messenger.send_onion_message(message, instructions);
///
/// // Create a blinded path to yourself, for someone to send an onion message to.
/// # let your_node_id = hop_node_id1;
@ -233,9 +233,9 @@ for OnionMessenger<ES, NS, L, NL, MR, OMH, APH, CMH> where
///
/// // Send a custom onion message to a blinded path.
/// let destination = Destination::BlindedPath(blinded_path);
/// let reply_path = None;
/// let instructions = MessageSendInstructions::WithoutReplyPath { destination };
/// # let message = YourCustomMessage {};
/// onion_messenger.send_onion_message(message, destination, reply_path);
/// onion_messenger.send_onion_message(message, instructions);
/// ```
///
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
@ -342,8 +342,8 @@ impl OnionMessageRecipient {
}
/// The `Responder` struct creates an appropriate [`ResponseInstruction`]
/// for responding to a message.
/// The `Responder` struct creates an appropriate [`ResponseInstruction`] for responding to a
/// message.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Responder {
/// The path along which a response can be sent.
@ -362,75 +362,74 @@ impl Responder {
}
}
/// Creates a [`ResponseInstruction::WithoutReplyPath`] for a given response.
/// Creates a [`ResponseInstruction`] for responding without including a reply path.
///
/// 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,
})
pub fn respond(self) -> ResponseInstruction {
ResponseInstruction {
destination: Destination::BlindedPath(self.reply_path),
context: None,
}
}
/// Creates a [`ResponseInstruction::WithReplyPath`] for a given response.
/// Creates a [`ResponseInstruction`] for responding including a reply path.
///
/// Use when the recipient needs to send back a reply to us.
pub fn respond_with_reply_path<T: OnionMessageContents>(self, response: T, context: MessageContext) -> ResponseInstruction<T> {
ResponseInstruction::WithReplyPath(OnionMessageResponse {
message: response,
reply_path: self.reply_path,
}, context)
pub fn respond_with_reply_path(self, context: MessageContext) -> ResponseInstruction {
ResponseInstruction {
destination: Destination::BlindedPath(self.reply_path),
context: Some(context),
}
}
}
/// This struct contains the information needed to reply to a received message.
pub struct OnionMessageResponse<T: OnionMessageContents> {
message: T,
reply_path: BlindedMessagePath,
/// Instructions for how and where to send the response to an onion message.
#[derive(Clone)]
pub struct ResponseInstruction {
/// The destination in a response is always a [`Destination::BlindedPath`] but using a
/// [`Destination`] rather than an explicit [`BlindedMessagePath`] simplifies the logic in
/// [`OnionMessenger::send_onion_message_internal`] somewhat.
destination: Destination,
context: Option<MessageContext>,
}
/// `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>, MessageContext),
/// Indicates that a response should be sent without including a reply path
/// for the recipient to respond back.
WithoutReplyPath(OnionMessageResponse<T>),
/// Indicates that there's no response to send back.
NoResponse,
impl ResponseInstruction {
fn into_instructions(self) -> MessageSendInstructions {
MessageSendInstructions::ForReply { instructions: self }
}
}
/// An [`OnionMessage`] for [`OnionMessenger`] to send.
///
/// These are obtained when released from [`OnionMessenger`]'s handlers after which they are
/// enqueued for sending.
#[cfg(not(c_bindings))]
pub struct PendingOnionMessage<T: OnionMessageContents> {
/// The message contents to send in an [`OnionMessage`].
pub contents: T,
/// The destination of the message.
pub destination: Destination,
/// A reply path to include in the [`OnionMessage`] for a response.
pub reply_path: Option<BlindedMessagePath>,
}
#[cfg(c_bindings)]
/// An [`OnionMessage`] for [`OnionMessenger`] to send.
///
/// These are obtained when released from [`OnionMessenger`]'s handlers after which they are
/// enqueued for sending.
pub type PendingOnionMessage<T> = (T, Destination, Option<BlindedMessagePath>);
pub(crate) fn new_pending_onion_message<T: OnionMessageContents>(
contents: T, destination: Destination, reply_path: Option<BlindedMessagePath>
) -> PendingOnionMessage<T> {
#[cfg(not(c_bindings))]
return PendingOnionMessage { contents, destination, reply_path };
#[cfg(c_bindings)]
return (contents, destination, reply_path);
/// Instructions for how and where to send a message.
#[derive(Clone)]
pub enum MessageSendInstructions {
/// Indicates that a message should be sent including the provided reply path for the recipient
/// to respond.
WithSpecifiedReplyPath {
/// The destination where we need to send our message.
destination: Destination,
/// The reply path which should be included in the message.
reply_path: BlindedMessagePath,
},
/// Indicates that a message should be sent including a reply path for the recipient to
/// respond.
WithReplyPath {
/// The destination where we need to send our message.
destination: Destination,
/// The context to include in the reply path we'll give the recipient so they can respond
/// to us.
context: MessageContext,
},
/// Indicates that a message should be sent without including a reply path, preventing the
/// recipient from responding.
WithoutReplyPath {
/// The destination where we need to send our message.
destination: Destination,
},
/// Indicates that a message is being sent as a reply to a received message.
ForReply {
/// The instructions provided by the [`Responder`].
instructions: ResponseInstruction,
},
}
/// A trait defining behavior for routing an [`OnionMessage`].
@ -799,7 +798,9 @@ 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, context: Option<Vec<u8>>, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage>;
fn handle_custom_message(
&self, message: Self::CustomMessage, context: Option<Vec<u8>>, responder: Option<Responder>
) -> Option<(Self::CustomMessage, ResponseInstruction)>;
/// Read a custom message of type `message_type` from `buffer`, returning `Ok(None)` if the
/// message type is unknown.
@ -809,15 +810,7 @@ pub trait CustomOnionMessageHandler {
///
/// Typically, this is used for messages initiating a message flow rather than in response to
/// another message. The latter should use the return value of [`Self::handle_custom_message`].
#[cfg(not(c_bindings))]
fn release_pending_custom_messages(&self) -> Vec<PendingOnionMessage<Self::CustomMessage>>;
/// Releases any [`Self::CustomMessage`]s that need to be sent.
///
/// Typically, this is used for messages initiating a message flow rather than in response to
/// another message. The latter should use the return value of [`Self::handle_custom_message`].
#[cfg(c_bindings)]
fn release_pending_custom_messages(&self) -> Vec<(Self::CustomMessage, Destination, Option<BlindedMessagePath>)>;
fn release_pending_custom_messages(&self) -> Vec<(Self::CustomMessage, MessageSendInstructions)>;
}
/// A processed incoming onion message, containing either a Forward (another onion message)
@ -1160,21 +1153,39 @@ where
self.offers_handler = offers_handler;
}
/// Sends an [`OnionMessage`] with the given `contents` to `destination`.
///
/// See [`OnionMessenger`] for example usage.
/// Sends an [`OnionMessage`] based on its [`MessageSendInstructions`].
pub fn send_onion_message<T: OnionMessageContents>(
&self, contents: T, destination: Destination, reply_path: Option<BlindedMessagePath>
&self, contents: T, instructions: MessageSendInstructions,
) -> Result<SendSuccess, SendError> {
self.find_path_and_enqueue_onion_message(
contents, destination, reply_path, format_args!("")
)
self.send_onion_message_internal(contents, instructions, format_args!(""))
}
fn find_path_and_enqueue_onion_message<T: OnionMessageContents>(
&self, contents: T, destination: Destination, reply_path: Option<BlindedMessagePath>,
log_suffix: fmt::Arguments
fn send_onion_message_internal<T: OnionMessageContents>(
&self, contents: T, instructions: MessageSendInstructions, log_suffix: fmt::Arguments,
) -> Result<SendSuccess, SendError> {
let (destination, reply_path) = match instructions {
MessageSendInstructions::WithSpecifiedReplyPath { destination, reply_path } =>
(destination, Some(reply_path)),
MessageSendInstructions::WithReplyPath { destination, context }
|MessageSendInstructions::ForReply { instructions: ResponseInstruction { destination, context: Some(context) } } =>
{
match self.create_blinded_path(context) {
Ok(reply_path) => (destination, Some(reply_path)),
Err(err) => {
log_trace!(
self.logger,
"Failed to create reply path {}: {:?}",
log_suffix, err
);
return Err(err);
}
}
},
MessageSendInstructions::WithoutReplyPath { destination }
|MessageSendInstructions::ForReply { instructions: ResponseInstruction { destination, context: None } } =>
(destination, None),
};
let mut logger = WithContext::from(&self.logger, None, None, None);
let result = self.find_path(destination).and_then(|path| {
let first_hop = path.intermediate_nodes.get(0).map(|p| *p);
@ -1318,42 +1329,21 @@ where
/// enqueueing any response for sending.
///
/// This function is useful for asynchronous handling of [`OnionMessage`]s.
/// Handlers have the option to return [`ResponseInstruction::NoResponse`], indicating that
/// no immediate response should be sent. Then, they can transfer the associated [`Responder`]
/// to another task responsible for generating the response asynchronously. Subsequently, when
/// the response is prepared and ready for sending, that task can invoke this method to enqueue
/// the response for delivery.
/// Handlers have the option to return `None`, indicating that no immediate response should be
/// sent. Then, they can transfer the associated [`Responder`] to another task responsible for
/// generating the response asynchronously. Subsequently, when the response is prepared and
/// ready for sending, that task can invoke this method to enqueue the response for delivery.
pub fn handle_onion_message_response<T: OnionMessageContents>(
&self, response: ResponseInstruction<T>
) -> Result<Option<SendSuccess>, SendError> {
let (response, context) = match response {
ResponseInstruction::WithReplyPath(response, context) => (response, Some(context)),
ResponseInstruction::WithoutReplyPath(response) => (response, None),
ResponseInstruction::NoResponse => return Ok(None),
};
let message_type = response.message.msg_type();
let reply_path = if let Some(context) = context {
match self.create_blinded_path(context) {
Ok(reply_path) => Some(reply_path),
Err(err) => {
log_trace!(
self.logger,
"Failed to create reply path when responding with {} to an onion message: {:?}",
message_type, err
);
return Err(err);
}
}
} else { None };
self.find_path_and_enqueue_onion_message(
response.message, Destination::BlindedPath(response.reply_path), reply_path,
&self, response: T, instructions: ResponseInstruction,
) -> Result<SendSuccess, SendError> {
let message_type = response.msg_type();
self.send_onion_message_internal(
response, instructions.into_instructions(),
format_args!(
"when responding with {} to an onion message",
message_type,
)
).map(|result| Some(result))
)
}
#[cfg(test)]
@ -1603,14 +1593,18 @@ where
}
};
let response_instructions = self.offers_handler.handle_message(msg, context, responder);
let _ = self.handle_onion_message_response(response_instructions);
if let Some((msg, instructions)) = response_instructions {
let _ = self.handle_onion_message_response(msg, instructions);
}
},
#[cfg(async_payments)]
ParsedOnionMessageContents::AsyncPayments(AsyncPaymentsMessage::HeldHtlcAvailable(msg)) => {
let response_instructions = self.async_payments_handler.held_htlc_available(
msg, responder
);
let _ = self.handle_onion_message_response(response_instructions);
if let Some((msg, instructions)) = response_instructions {
let _ = self.handle_onion_message_response(msg, instructions);
}
},
#[cfg(async_payments)]
ParsedOnionMessageContents::AsyncPayments(AsyncPaymentsMessage::ReleaseHeldHtlc(msg)) => {
@ -1626,7 +1620,9 @@ where
}
};
let response_instructions = self.custom_handler.handle_custom_message(msg, context, responder);
let _ = self.handle_onion_message_response(response_instructions);
if let Some((msg, instructions)) = response_instructions {
let _ = self.handle_onion_message_response(msg, instructions);
}
},
}
},
@ -1751,24 +1747,16 @@ where
// node, and then enqueue the message for sending to the first peer in the full path.
fn next_onion_message_for_peer(&self, peer_node_id: PublicKey) -> Option<OnionMessage> {
// Enqueue any initiating `OffersMessage`s to send.
for message in self.offers_handler.release_pending_messages() {
#[cfg(not(c_bindings))]
let PendingOnionMessage { contents, destination, reply_path } = message;
#[cfg(c_bindings)]
let (contents, destination, reply_path) = message;
let _ = self.find_path_and_enqueue_onion_message(
contents, destination, reply_path, format_args!("when sending OffersMessage")
for (message, instructions) in self.offers_handler.release_pending_messages() {
let _ = self.send_onion_message_internal(
message, instructions, format_args!("when sending OffersMessage")
);
}
// Enqueue any initiating `CustomMessage`s to send.
for message in self.custom_handler.release_pending_custom_messages() {
#[cfg(not(c_bindings))]
let PendingOnionMessage { contents, destination, reply_path } = message;
#[cfg(c_bindings)]
let (contents, destination, reply_path) = message;
let _ = self.find_path_and_enqueue_onion_message(
contents, destination, reply_path, format_args!("when sending CustomMessage")
for (message, instructions) in self.custom_handler.release_pending_custom_messages() {
let _ = self.send_onion_message_internal(
message, instructions, format_args!("when sending CustomMessage")
);
}

View file

@ -22,9 +22,7 @@ use crate::offers::static_invoice::StaticInvoice;
use crate::onion_message::packet::OnionMessageContents;
use crate::util::logger::Logger;
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
use crate::onion_message::messenger::{ResponseInstruction, Responder};
#[cfg(not(c_bindings))]
use crate::onion_message::messenger::PendingOnionMessage;
use crate::onion_message::messenger::{ResponseInstruction, Responder, MessageSendInstructions};
use crate::prelude::*;
@ -47,21 +45,13 @@ pub trait OffersMessageHandler {
/// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger
fn handle_message(
&self, message: OffersMessage, context: Option<OffersContext>, responder: Option<Responder>,
) -> ResponseInstruction<OffersMessage>;
) -> Option<(OffersMessage, ResponseInstruction)>;
/// Releases any [`OffersMessage`]s that need to be sent.
///
/// Typically, this is used for messages initiating a payment flow rather than in response to
/// another message. The latter should use the return value of [`Self::handle_message`].
#[cfg(not(c_bindings))]
fn release_pending_messages(&self) -> Vec<PendingOnionMessage<OffersMessage>> { vec![] }
/// Releases any [`OffersMessage`]s that need to be sent.
///
/// Typically, this is used for messages initiating a payment flow rather than in response to
/// another message. The latter should use the return value of [`Self::handle_message`].
#[cfg(c_bindings)]
fn release_pending_messages(&self) -> Vec<(OffersMessage, crate::onion_message::messenger::Destination, Option<crate::blinded_path::message::BlindedMessagePath>)> { vec![] }
fn release_pending_messages(&self) -> Vec<(OffersMessage, MessageSendInstructions)> { vec![] }
}
/// Possible BOLT 12 Offers messages sent and received via an [`OnionMessage`].