Skip to content

Commit f8db8f9

Browse files
committed
Move request_refund_payment to OffersMessageFlow
1 parent 8e7c5f1 commit f8db8f9

File tree

3 files changed

+201
-169
lines changed

3 files changed

+201
-169
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 9 additions & 152 deletions
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};
@@ -66,11 +66,11 @@ use crate::ln::msgs::{ChannelMessageHandler, CommitmentUpdate, DecodeError, Ligh
6666
#[cfg(test)]
6767
use crate::ln::outbound_payment;
6868
use crate::ln::outbound_payment::{OutboundPayments, PendingOutboundPayment, RetryableInvoiceRequest, SendAlongPathArgs, StaleExpiration};
69-
use crate::offers::invoice::{Bolt12Invoice, DerivedSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice, DEFAULT_RELATIVE_EXPIRY};
69+
use crate::offers::invoice::Bolt12Invoice;
70+
use crate::offers::invoice::UnsignedBolt12Invoice;
7071
use crate::offers::invoice_request::{InvoiceRequest, InvoiceRequestBuilder};
7172
use crate::offers::nonce::Nonce;
7273
use crate::offers::parse::Bolt12SemanticError;
73-
use crate::offers::refund::Refund;
7474
use crate::offers::signer;
7575
#[cfg(async_payments)]
7676
use crate::offers::static_invoice::StaticInvoice;
@@ -2028,53 +2028,8 @@ where
20282028
///
20292029
/// For more information on creating refunds, see [`create_refund_builder`].
20302030
///
2031-
/// Use [`request_refund_payment`] to send a [`Bolt12Invoice`] for receiving the refund. Similar to
2032-
/// *creating* an [`Offer`], this is stateless as it represents an inbound payment.
2033-
///
2034-
/// ```
2035-
/// # use lightning::events::{Event, EventsProvider, PaymentPurpose};
2036-
/// # use lightning::ln::channelmanager::AChannelManager;
2037-
/// # use lightning::offers::flow::OffersMessageCommons;
2038-
/// # use lightning::offers::refund::Refund;
2039-
/// #
2040-
/// # fn example<T: AChannelManager>(channel_manager: T, refund: &Refund) {
2041-
/// # let channel_manager = channel_manager.get_cm();
2042-
/// let known_payment_hash = match channel_manager.request_refund_payment(refund) {
2043-
/// Ok(invoice) => {
2044-
/// let payment_hash = invoice.payment_hash();
2045-
/// println!("Requesting refund payment {}", payment_hash);
2046-
/// payment_hash
2047-
/// },
2048-
/// Err(e) => panic!("Unable to request payment for refund: {:?}", e),
2049-
/// };
2050-
///
2051-
/// // On the event processing thread
2052-
/// channel_manager.process_pending_events(&|event| {
2053-
/// match event {
2054-
/// Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose {
2055-
/// PaymentPurpose::Bolt12RefundPayment { payment_preimage: Some(payment_preimage), .. } => {
2056-
/// assert_eq!(payment_hash, known_payment_hash);
2057-
/// println!("Claiming payment {}", payment_hash);
2058-
/// channel_manager.claim_funds(payment_preimage);
2059-
/// },
2060-
/// PaymentPurpose::Bolt12RefundPayment { payment_preimage: None, .. } => {
2061-
/// println!("Unknown payment hash: {}", payment_hash);
2062-
/// },
2063-
/// // ...
2064-
/// # _ => {},
2065-
/// },
2066-
/// Event::PaymentClaimed { payment_hash, amount_msat, .. } => {
2067-
/// assert_eq!(payment_hash, known_payment_hash);
2068-
/// println!("Claimed {} msats", amount_msat);
2069-
/// },
2070-
/// // ...
2071-
/// # _ => {},
2072-
/// }
2073-
/// Ok(())
2074-
/// });
2075-
/// # }
2076-
/// ```
2077-
///
2031+
/// For requesting refund payments, see [`request_refund_payment`].
2032+
///
20782033
/// # Persistence
20792034
///
20802035
/// Implements [`Writeable`] to write out all channel state to disk. Implies [`peer_disconnected`] for
@@ -2155,7 +2110,7 @@ where
21552110
/// [`offers`]: crate::offers
21562111
/// [`Offer`]: crate::offers::offer
21572112
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
2158-
/// [`request_refund_payment`]: Self::request_refund_payment
2113+
/// [`request_refund_payment`]: crate::offers::flow::OffersMessageFlow::request_refund_payment
21592114
/// [`peer_disconnected`]: msgs::ChannelMessageHandler::peer_disconnected
21602115
/// [`funding_created`]: msgs::FundingCreated
21612116
/// [`funding_transaction_generated`]: Self::funding_transaction_generated
@@ -2678,6 +2633,7 @@ const MAX_NO_CHANNEL_PEERS: usize = 250;
26782633
/// become invalid over time as channels are closed. Thus, they are only suitable for short-term use.
26792634
///
26802635
/// [`Offer`]: crate::offers::offer
2636+
/// [`Refund`]: crate::offers::refund
26812637
pub const MAX_SHORT_LIVED_RELATIVE_EXPIRY: Duration = Duration::from_secs(60 * 60 * 24);
26822638

26832639
/// Used by [`ChannelManager::list_recent_payments`] to express the status of recent payments.
@@ -9853,7 +9809,7 @@ where
98539809
/// Sending multiple requests increases the chances of successful delivery in case some
98549810
/// paths are unavailable. However, only one invoice for a given [`PaymentId`] will be paid,
98559811
/// even if multiple invoices are received.
9856-
const OFFERS_MESSAGE_REQUEST_LIMIT: usize = 10;
9812+
pub const OFFERS_MESSAGE_REQUEST_LIMIT: usize = 10;
98579813

98589814
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>
98599815
where
@@ -9867,106 +9823,6 @@ where
98679823
MR::Target: MessageRouter,
98689824
L::Target: Logger,
98699825
{
9870-
/// Creates a [`Bolt12Invoice`] for a [`Refund`] and enqueues it to be sent via an onion
9871-
/// message.
9872-
///
9873-
/// The resulting invoice uses a [`PaymentHash`] recognized by the [`ChannelManager`] and a
9874-
/// [`BlindedPaymentPath`] containing the [`PaymentSecret`] needed to reconstruct the
9875-
/// corresponding [`PaymentPreimage`]. It is returned purely for informational purposes.
9876-
///
9877-
/// # Limitations
9878-
///
9879-
/// Requires a direct connection to an introduction node in [`Refund::paths`] or to
9880-
/// [`Refund::payer_signing_pubkey`], if empty. This request is best effort; an invoice will be
9881-
/// sent to each node meeting the aforementioned criteria, but there's no guarantee that they
9882-
/// will be received and no retries will be made.
9883-
///
9884-
/// # Errors
9885-
///
9886-
/// Errors if:
9887-
/// - the refund is for an unsupported chain, or
9888-
/// - the parameterized [`Router`] is unable to create a blinded payment path or reply path for
9889-
/// the invoice.
9890-
///
9891-
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
9892-
pub fn request_refund_payment(
9893-
&self, refund: &Refund
9894-
) -> Result<Bolt12Invoice, Bolt12SemanticError> {
9895-
let expanded_key = &self.inbound_payment_key;
9896-
let entropy = &*self.entropy_source;
9897-
let secp_ctx = &self.secp_ctx;
9898-
9899-
let amount_msats = refund.amount_msats();
9900-
let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32;
9901-
9902-
if refund.chain() != self.chain_hash {
9903-
return Err(Bolt12SemanticError::UnsupportedChain);
9904-
}
9905-
9906-
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
9907-
9908-
match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) {
9909-
Ok((payment_hash, payment_secret)) => {
9910-
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
9911-
let payment_paths = self.create_blinded_payment_paths(
9912-
amount_msats, payment_secret, payment_context
9913-
)
9914-
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
9915-
9916-
#[cfg(feature = "std")]
9917-
let builder = refund.respond_using_derived_keys(
9918-
payment_paths, payment_hash, expanded_key, entropy
9919-
)?;
9920-
#[cfg(not(feature = "std"))]
9921-
let created_at = Duration::from_secs(
9922-
self.highest_seen_timestamp.load(Ordering::Acquire) as u64
9923-
);
9924-
#[cfg(not(feature = "std"))]
9925-
let builder = refund.respond_using_derived_keys_no_std(
9926-
payment_paths, payment_hash, created_at, expanded_key, entropy
9927-
)?;
9928-
let builder: InvoiceBuilder<DerivedSigningPubkey> = builder.into();
9929-
let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
9930-
9931-
let nonce = Nonce::from_entropy_source(entropy);
9932-
let hmac = payment_hash.hmac_for_offer_payment(nonce, expanded_key);
9933-
let context = MessageContext::Offers(OffersContext::InboundPayment {
9934-
payment_hash: invoice.payment_hash(), nonce, hmac
9935-
});
9936-
let reply_paths = self.create_blinded_paths(context)
9937-
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
9938-
9939-
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
9940-
if refund.paths().is_empty() {
9941-
for reply_path in reply_paths {
9942-
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
9943-
destination: Destination::Node(refund.payer_signing_pubkey()),
9944-
reply_path,
9945-
};
9946-
let message = OffersMessage::Invoice(invoice.clone());
9947-
pending_offers_messages.push((message, instructions));
9948-
}
9949-
} else {
9950-
reply_paths
9951-
.iter()
9952-
.flat_map(|reply_path| refund.paths().iter().map(move |path| (path, reply_path)))
9953-
.take(OFFERS_MESSAGE_REQUEST_LIMIT)
9954-
.for_each(|(path, reply_path)| {
9955-
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
9956-
destination: Destination::BlindedPath(path.clone()),
9957-
reply_path: reply_path.clone(),
9958-
};
9959-
let message = OffersMessage::Invoice(invoice.clone());
9960-
pending_offers_messages.push((message, instructions));
9961-
});
9962-
}
9963-
9964-
Ok(invoice)
9965-
},
9966-
Err(()) => Err(Bolt12SemanticError::InvalidAmount),
9967-
}
9968-
}
9969-
99709826
/// Pays for an [`Offer`] looked up using [BIP 353] Human Readable Names resolved by the DNS
99719827
/// resolver(s) at `dns_resolvers` which resolve names according to bLIP 32.
99729828
///
@@ -12436,6 +12292,7 @@ where
1243612292
/// [`Refund`]s, and any reply paths.
1243712293
///
1243812294
/// [`Offer`]: crate::offers::offer
12295+
/// [`Refund`]: crate::offers::refund
1243912296
pub message_router: MR,
1244012297
/// The Logger for use in the ChannelManager and which may be used to log information during
1244112298
/// deserialization.

lightning/src/ln/offers_tests.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() {
654654
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
655655

656656
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
657-
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
657+
let expected_invoice = alice.offers_handler.request_refund_payment(&refund).unwrap();
658658

659659
connect_peers(alice, charlie);
660660

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

785785
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
786-
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
786+
let expected_invoice = alice.offers_handler.request_refund_payment(&refund).unwrap();
787787

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

890890
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
891-
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
891+
let expected_invoice = alice.offers_handler.request_refund_payment(&refund).unwrap();
892892

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

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

10481048
connect_peers(david, bob);
10491049

@@ -1247,7 +1247,7 @@ fn creates_refund_with_blinded_path_using_unannounced_introduction_node() {
12471247
}
12481248
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
12491249

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

12521252
let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
12531253

@@ -1531,7 +1531,7 @@ fn fails_authentication_when_handling_invoice_for_refund() {
15311531
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
15321532

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

15361536
connect_peers(david, alice);
15371537
match &mut alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
@@ -1563,7 +1563,7 @@ fn fails_authentication_when_handling_invoice_for_refund() {
15631563
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(charlie_id));
15641564
}
15651565

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

15681568
match &mut alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
15691569
MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } =>
@@ -1696,7 +1696,7 @@ fn fails_creating_refund_or_sending_invoice_without_connected_peers() {
16961696
.unwrap()
16971697
.build().unwrap();
16981698

1699-
match alice.node.request_refund_payment(&refund) {
1699+
match alice.offers_handler.request_refund_payment(&refund) {
17001700
Ok(_) => panic!("Expected error"),
17011701
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
17021702
}
@@ -1705,7 +1705,7 @@ fn fails_creating_refund_or_sending_invoice_without_connected_peers() {
17051705
args.send_channel_ready = (true, true);
17061706
reconnect_nodes(args);
17071707

1708-
assert!(alice.node.request_refund_payment(&refund).is_ok());
1708+
assert!(alice.offers_handler.request_refund_payment(&refund).is_ok());
17091709
}
17101710

17111711
/// Fails creating an invoice request when the offer contains an unsupported chain.
@@ -1755,7 +1755,7 @@ fn fails_sending_invoice_with_unsupported_chain_for_refund() {
17551755
.chain(Network::Signet)
17561756
.build().unwrap();
17571757

1758-
match alice.node.request_refund_payment(&refund) {
1758+
match alice.offers_handler.request_refund_payment(&refund) {
17591759
Ok(_) => panic!("Expected error"),
17601760
Err(e) => assert_eq!(e, Bolt12SemanticError::UnsupportedChain),
17611761
}
@@ -1978,7 +1978,7 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_refund() {
19781978
.unwrap()
19791979
.build().unwrap();
19801980

1981-
match alice.node.request_refund_payment(&refund) {
1981+
match alice.offers_handler.request_refund_payment(&refund) {
19821982
Ok(_) => panic!("Expected error"),
19831983
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
19841984
}
@@ -2029,7 +2029,7 @@ fn fails_paying_invoice_more_than_once() {
20292029
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
20302030

20312031
// Alice sends the first invoice
2032-
alice.node.request_refund_payment(&refund).unwrap();
2032+
alice.offers_handler.request_refund_payment(&refund).unwrap();
20332033

20342034
connect_peers(alice, charlie);
20352035

@@ -2049,7 +2049,7 @@ fn fails_paying_invoice_more_than_once() {
20492049
disconnect_peers(alice, &[charlie]);
20502050

20512051
// Alice sends the second invoice
2052-
alice.node.request_refund_payment(&refund).unwrap();
2052+
alice.offers_handler.request_refund_payment(&refund).unwrap();
20532053

20542054
connect_peers(alice, charlie);
20552055
connect_peers(david, bob);

0 commit comments

Comments
 (0)