mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-24 15:02:20 +01:00
Merge pull request #3263 from TheBlueMatt/2024-08-bindings-om
Remove message type bound on `ResponseInstruction`
This commit is contained in:
commit
49dfa5a496
8 changed files with 274 additions and 307 deletions
|
@ -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![]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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![]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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![]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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")
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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`].
|
||||
|
|
Loading…
Add table
Reference in a new issue