Skip to content

Commit e038951

Browse files
committed
Move request_refund_payment to OffersMessageFlow
1 parent a59b356 commit e038951

File tree

3 files changed

+192
-167
lines changed

3 files changed

+192
-167
lines changed

lightning/src/ln/channelmanager.rs

+5-152
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use crate::events::FundingInfo;
3636
use crate::blinded_path::message::{AsyncPaymentsContext, MessageContext, OffersContext};
3737
use crate::blinded_path::NodeIdLookUp;
3838
use crate::blinded_path::message::{BlindedMessagePath, MessageForwardNode};
39-
use crate::blinded_path::payment::{BlindedPaymentPath, Bolt12RefundContext, PaymentConstraints, PaymentContext, ReceiveTlvs};
39+
use crate::blinded_path::payment::{BlindedPaymentPath, PaymentConstraints, PaymentContext, ReceiveTlvs};
4040
use crate::chain;
4141
use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock};
4242
use crate::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator};
@@ -65,11 +65,10 @@ use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
6565
use crate::ln::outbound_payment;
6666
use crate::ln::outbound_payment::{OutboundPayments, PendingOutboundPayment, RetryableInvoiceRequest, SendAlongPathArgs, StaleExpiration};
6767
use crate::ln::wire::Encode;
68-
use crate::offers::invoice::{Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, InvoiceBuilder};
68+
use crate::offers::invoice::Bolt12Invoice;
6969
use crate::offers::invoice_request::{InvoiceRequest, InvoiceRequestBuilder};
7070
use crate::offers::nonce::Nonce;
7171
use crate::offers::parse::Bolt12SemanticError;
72-
use crate::offers::refund::Refund;
7372
use crate::offers::signer;
7473
#[cfg(async_payments)]
7574
use crate::offers::static_invoice::StaticInvoice;
@@ -1993,54 +1992,6 @@ where
19931992
/// # }
19941993
/// ```
19951994
///
1996-
/// ## BOLT 12 Refunds
1997-
///
1998-
/// Use [`request_refund_payment`] to send a [`Bolt12Invoice`] for receiving the refund. Similar to
1999-
/// *creating* an [`Offer`], this is stateless as it represents an inbound payment.
2000-
///
2001-
/// ```
2002-
/// # use lightning::events::{Event, EventsProvider, PaymentPurpose};
2003-
/// # use lightning::ln::channelmanager::{AChannelManager, OffersMessageCommons};
2004-
/// # use lightning::offers::refund::Refund;
2005-
/// #
2006-
/// # fn example<T: AChannelManager>(channel_manager: T, refund: &Refund) {
2007-
/// # let channel_manager = channel_manager.get_cm();
2008-
/// let known_payment_hash = match channel_manager.request_refund_payment(refund) {
2009-
/// Ok(invoice) => {
2010-
/// let payment_hash = invoice.payment_hash();
2011-
/// println!("Requesting refund payment {}", payment_hash);
2012-
/// payment_hash
2013-
/// },
2014-
/// Err(e) => panic!("Unable to request payment for refund: {:?}", e),
2015-
/// };
2016-
///
2017-
/// // On the event processing thread
2018-
/// channel_manager.process_pending_events(&|event| {
2019-
/// match event {
2020-
/// Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose {
2021-
/// PaymentPurpose::Bolt12RefundPayment { payment_preimage: Some(payment_preimage), .. } => {
2022-
/// assert_eq!(payment_hash, known_payment_hash);
2023-
/// println!("Claiming payment {}", payment_hash);
2024-
/// channel_manager.claim_funds(payment_preimage);
2025-
/// },
2026-
/// PaymentPurpose::Bolt12RefundPayment { payment_preimage: None, .. } => {
2027-
/// println!("Unknown payment hash: {}", payment_hash);
2028-
/// },
2029-
/// // ...
2030-
/// # _ => {},
2031-
/// },
2032-
/// Event::PaymentClaimed { payment_hash, amount_msat, .. } => {
2033-
/// assert_eq!(payment_hash, known_payment_hash);
2034-
/// println!("Claimed {} msats", amount_msat);
2035-
/// },
2036-
/// // ...
2037-
/// # _ => {},
2038-
/// }
2039-
/// Ok(())
2040-
/// });
2041-
/// # }
2042-
/// ```
2043-
///
20441995
/// # Persistence
20451996
///
20461997
/// Implements [`Writeable`] to write out all channel state to disk. Implies [`peer_disconnected`] for
@@ -2633,6 +2584,7 @@ const MAX_NO_CHANNEL_PEERS: usize = 250;
26332584
/// become invalid over time as channels are closed. Thus, they are only suitable for short-term use.
26342585
///
26352586
/// [`Offer`]: crate::offers::offer
2587+
/// [`Refund`]: crate::offers::refund
26362588
pub const MAX_SHORT_LIVED_RELATIVE_EXPIRY: Duration = Duration::from_secs(60 * 60 * 24);
26372589

26382590
/// Used by [`ChannelManager::list_recent_payments`] to express the status of recent payments.
@@ -9573,7 +9525,7 @@ where
95739525
/// Sending multiple requests increases the chances of successful delivery in case some
95749526
/// paths are unavailable. However, only one invoice for a given [`PaymentId`] will be paid,
95759527
/// even if multiple invoices are received.
9576-
const OFFERS_MESSAGE_REQUEST_LIMIT: usize = 10;
9528+
pub const OFFERS_MESSAGE_REQUEST_LIMIT: usize = 10;
95779529

95789530
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, MR: Deref, L: Deref> ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
95799531
where
@@ -9587,106 +9539,6 @@ where
95879539
MR::Target: MessageRouter,
95889540
L::Target: Logger,
95899541
{
9590-
/// Creates a [`Bolt12Invoice`] for a [`Refund`] and enqueues it to be sent via an onion
9591-
/// message.
9592-
///
9593-
/// The resulting invoice uses a [`PaymentHash`] recognized by the [`ChannelManager`] and a
9594-
/// [`BlindedPaymentPath`] containing the [`PaymentSecret`] needed to reconstruct the
9595-
/// corresponding [`PaymentPreimage`]. It is returned purely for informational purposes.
9596-
///
9597-
/// # Limitations
9598-
///
9599-
/// Requires a direct connection to an introduction node in [`Refund::paths`] or to
9600-
/// [`Refund::payer_signing_pubkey`], if empty. This request is best effort; an invoice will be
9601-
/// sent to each node meeting the aforementioned criteria, but there's no guarantee that they
9602-
/// will be received and no retries will be made.
9603-
///
9604-
/// # Errors
9605-
///
9606-
/// Errors if:
9607-
/// - the refund is for an unsupported chain, or
9608-
/// - the parameterized [`Router`] is unable to create a blinded payment path or reply path for
9609-
/// the invoice.
9610-
///
9611-
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
9612-
pub fn request_refund_payment(
9613-
&self, refund: &Refund
9614-
) -> Result<Bolt12Invoice, Bolt12SemanticError> {
9615-
let expanded_key = &self.inbound_payment_key;
9616-
let entropy = &*self.entropy_source;
9617-
let secp_ctx = &self.secp_ctx;
9618-
9619-
let amount_msats = refund.amount_msats();
9620-
let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32;
9621-
9622-
if refund.chain() != self.chain_hash {
9623-
return Err(Bolt12SemanticError::UnsupportedChain);
9624-
}
9625-
9626-
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
9627-
9628-
match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) {
9629-
Ok((payment_hash, payment_secret)) => {
9630-
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
9631-
let payment_paths = self.create_blinded_payment_paths(
9632-
amount_msats, payment_secret, payment_context
9633-
)
9634-
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
9635-
9636-
#[cfg(feature = "std")]
9637-
let builder = refund.respond_using_derived_keys(
9638-
payment_paths, payment_hash, expanded_key, entropy
9639-
)?;
9640-
#[cfg(not(feature = "std"))]
9641-
let created_at = Duration::from_secs(
9642-
self.highest_seen_timestamp.load(Ordering::Acquire) as u64
9643-
);
9644-
#[cfg(not(feature = "std"))]
9645-
let builder = refund.respond_using_derived_keys_no_std(
9646-
payment_paths, payment_hash, created_at, expanded_key, entropy
9647-
)?;
9648-
let builder: InvoiceBuilder<DerivedSigningPubkey> = builder.into();
9649-
let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
9650-
9651-
let nonce = Nonce::from_entropy_source(entropy);
9652-
let hmac = payment_hash.hmac_for_offer_payment(nonce, expanded_key);
9653-
let context = MessageContext::Offers(OffersContext::InboundPayment {
9654-
payment_hash: invoice.payment_hash(), nonce, hmac
9655-
});
9656-
let reply_paths = self.create_blinded_paths(context)
9657-
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
9658-
9659-
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
9660-
if refund.paths().is_empty() {
9661-
for reply_path in reply_paths {
9662-
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
9663-
destination: Destination::Node(refund.payer_signing_pubkey()),
9664-
reply_path,
9665-
};
9666-
let message = OffersMessage::Invoice(invoice.clone());
9667-
pending_offers_messages.push((message, instructions));
9668-
}
9669-
} else {
9670-
reply_paths
9671-
.iter()
9672-
.flat_map(|reply_path| refund.paths().iter().map(move |path| (path, reply_path)))
9673-
.take(OFFERS_MESSAGE_REQUEST_LIMIT)
9674-
.for_each(|(path, reply_path)| {
9675-
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
9676-
destination: Destination::BlindedPath(path.clone()),
9677-
reply_path: reply_path.clone(),
9678-
};
9679-
let message = OffersMessage::Invoice(invoice.clone());
9680-
pending_offers_messages.push((message, instructions));
9681-
});
9682-
}
9683-
9684-
Ok(invoice)
9685-
},
9686-
Err(()) => Err(Bolt12SemanticError::InvalidAmount),
9687-
}
9688-
}
9689-
96909542
/// Pays for an [`Offer`] looked up using [BIP 353] Human Readable Names resolved by the DNS
96919543
/// resolver(s) at `dns_resolvers` which resolve names according to bLIP 32.
96929544
///
@@ -12133,6 +11985,7 @@ where
1213311985
/// [`Refund`]s, and any reply paths.
1213411986
///
1213511987
/// [`Offer`]: crate::offers::offer
11988+
/// [`Refund`]: crate::offers::refund
1213611989
pub message_router: MR,
1213711990
/// The Logger for use in the ChannelManager and which may be used to log information during
1213811991
/// deserialization.

lightning/src/ln/offers_tests.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() {
655655
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
656656

657657
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
658-
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
658+
let expected_invoice = alice.offers_handler.request_refund_payment(&refund).unwrap();
659659

660660
connect_peers(alice, charlie);
661661

@@ -784,7 +784,7 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() {
784784
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
785785

786786
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
787-
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
787+
let expected_invoice = alice.offers_handler.request_refund_payment(&refund).unwrap();
788788

789789
let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
790790
bob.onion_messenger.handle_onion_message(alice_id, &onion_message);
@@ -889,7 +889,7 @@ fn pays_for_refund_without_blinded_paths() {
889889
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
890890

891891
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
892-
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
892+
let expected_invoice = alice.offers_handler.request_refund_payment(&refund).unwrap();
893893

894894
let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
895895
bob.onion_messenger.handle_onion_message(alice_id, &onion_message);
@@ -1044,7 +1044,7 @@ fn send_invoice_for_refund_with_distinct_reply_path() {
10441044
}
10451045
expect_recent_payment!(alice, RecentPaymentDetails::AwaitingInvoice, payment_id);
10461046

1047-
let _expected_invoice = david.node.request_refund_payment(&refund).unwrap();
1047+
let _expected_invoice = david.offers_handler.request_refund_payment(&refund).unwrap();
10481048

10491049
connect_peers(david, bob);
10501050

@@ -1324,7 +1324,7 @@ fn creates_refund_with_blinded_path_using_unannounced_introduction_node() {
13241324
}
13251325
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
13261326

1327-
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
1327+
let expected_invoice = alice.offers_handler.request_refund_payment(&refund).unwrap();
13281328

13291329
let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
13301330

@@ -1608,7 +1608,7 @@ fn fails_authentication_when_handling_invoice_for_refund() {
16081608
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
16091609

16101610
// Send the invoice directly to David instead of using a blinded path.
1611-
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
1611+
let expected_invoice = alice.offers_handler.request_refund_payment(&refund).unwrap();
16121612

16131613
connect_peers(david, alice);
16141614
match &mut alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
@@ -1640,7 +1640,7 @@ fn fails_authentication_when_handling_invoice_for_refund() {
16401640
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(charlie_id));
16411641
}
16421642

1643-
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
1643+
let expected_invoice = alice.offers_handler.request_refund_payment(&refund).unwrap();
16441644

16451645
match &mut alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
16461646
MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } =>
@@ -1773,7 +1773,7 @@ fn fails_creating_refund_or_sending_invoice_without_connected_peers() {
17731773
.unwrap()
17741774
.build().unwrap();
17751775

1776-
match alice.node.request_refund_payment(&refund) {
1776+
match alice.offers_handler.request_refund_payment(&refund) {
17771777
Ok(_) => panic!("Expected error"),
17781778
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
17791779
}
@@ -1782,7 +1782,7 @@ fn fails_creating_refund_or_sending_invoice_without_connected_peers() {
17821782
args.send_channel_ready = (true, true);
17831783
reconnect_nodes(args);
17841784

1785-
assert!(alice.node.request_refund_payment(&refund).is_ok());
1785+
assert!(alice.offers_handler.request_refund_payment(&refund).is_ok());
17861786
}
17871787

17881788
/// Fails creating an invoice request when the offer contains an unsupported chain.
@@ -1832,7 +1832,7 @@ fn fails_sending_invoice_with_unsupported_chain_for_refund() {
18321832
.chain(Network::Signet)
18331833
.build().unwrap();
18341834

1835-
match alice.node.request_refund_payment(&refund) {
1835+
match alice.offers_handler.request_refund_payment(&refund) {
18361836
Ok(_) => panic!("Expected error"),
18371837
Err(e) => assert_eq!(e, Bolt12SemanticError::UnsupportedChain),
18381838
}
@@ -2055,7 +2055,7 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_refund() {
20552055
.unwrap()
20562056
.build().unwrap();
20572057

2058-
match alice.node.request_refund_payment(&refund) {
2058+
match alice.offers_handler.request_refund_payment(&refund) {
20592059
Ok(_) => panic!("Expected error"),
20602060
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
20612061
}
@@ -2106,7 +2106,7 @@ fn fails_paying_invoice_more_than_once() {
21062106
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
21072107

21082108
// Alice sends the first invoice
2109-
alice.node.request_refund_payment(&refund).unwrap();
2109+
alice.offers_handler.request_refund_payment(&refund).unwrap();
21102110

21112111
connect_peers(alice, charlie);
21122112

@@ -2126,7 +2126,7 @@ fn fails_paying_invoice_more_than_once() {
21262126
disconnect_peers(alice, &[charlie]);
21272127

21282128
// Alice sends the second invoice
2129-
alice.node.request_refund_payment(&refund).unwrap();
2129+
alice.offers_handler.request_refund_payment(&refund).unwrap();
21302130

21312131
connect_peers(alice, charlie);
21322132
connect_peers(david, bob);

0 commit comments

Comments
 (0)