Skip to content

Commit 58b9fd2

Browse files
committed
Move create_refund_builder to OffersMessageFlow
1 parent 9705a65 commit 58b9fd2

File tree

5 files changed

+243
-216
lines changed

5 files changed

+243
-216
lines changed

lightning/src/ln/channelmanager.rs

+57-192
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ use crate::offers::invoice_request::{InvoiceRequest, InvoiceRequestBuilder};
6969
use crate::offers::nonce::Nonce;
7070
use crate::offers::offer::Offer;
7171
use crate::offers::parse::Bolt12SemanticError;
72-
use crate::offers::refund::{Refund, RefundBuilder};
72+
use crate::offers::refund::Refund;
7373
use crate::offers::signer;
7474
#[cfg(async_payments)]
7575
use crate::offers::static_invoice::StaticInvoice;
@@ -1948,7 +1948,7 @@ where
19481948
/// ```
19491949
/// # use lightning::events::{Event, EventsProvider};
19501950
/// # use lightning::types::payment::PaymentHash;
1951-
/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, RecipientOnionFields, Retry};
1951+
/// # use lightning::ln::channelmanager::{AChannelManager, OffersMessageCommons, PaymentId, RecentPaymentDetails, RecipientOnionFields, Retry};
19521952
/// # use lightning::routing::router::RouteParameters;
19531953
/// #
19541954
/// # fn example<T: AChannelManager>(
@@ -2000,7 +2000,7 @@ where
20002000
///
20012001
/// ```
20022002
/// # use lightning::events::{Event, EventsProvider};
2003-
/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, Retry};
2003+
/// # use lightning::ln::channelmanager::{AChannelManager, OffersMessageCommons, PaymentId, RecentPaymentDetails, Retry};
20042004
/// # use lightning::offers::offer::Offer;
20052005
/// #
20062006
/// # fn example<T: AChannelManager>(
@@ -2048,67 +2048,6 @@ where
20482048
///
20492049
/// ## BOLT 12 Refunds
20502050
///
2051-
/// A [`Refund`] is a request for an invoice to be paid. Like *paying* for an [`Offer`], *creating*
2052-
/// a [`Refund`] involves maintaining state since it represents a future outbound payment.
2053-
/// Therefore, use [`create_refund_builder`] when creating one, otherwise [`ChannelManager`] will
2054-
/// refuse to pay any corresponding [`Bolt12Invoice`] that it receives.
2055-
///
2056-
/// ```
2057-
/// # use core::time::Duration;
2058-
/// # use lightning::events::{Event, EventsProvider};
2059-
/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, Retry};
2060-
/// # use lightning::offers::parse::Bolt12SemanticError;
2061-
/// #
2062-
/// # fn example<T: AChannelManager>(
2063-
/// # channel_manager: T, amount_msats: u64, absolute_expiry: Duration, retry: Retry,
2064-
/// # max_total_routing_fee_msat: Option<u64>
2065-
/// # ) -> Result<(), Bolt12SemanticError> {
2066-
/// # let channel_manager = channel_manager.get_cm();
2067-
/// let payment_id = PaymentId([42; 32]);
2068-
/// let refund = channel_manager
2069-
/// .create_refund_builder(
2070-
/// amount_msats, absolute_expiry, payment_id, retry, max_total_routing_fee_msat
2071-
/// )?
2072-
/// # ;
2073-
/// # // Needed for compiling for c_bindings
2074-
/// # let builder: lightning::offers::refund::RefundBuilder<_> = refund.into();
2075-
/// # let refund = builder
2076-
/// .description("coffee".to_string())
2077-
/// .payer_note("refund for order 1234".to_string())
2078-
/// .build()?;
2079-
/// let bech32_refund = refund.to_string();
2080-
///
2081-
/// // First the payment will be waiting on an invoice
2082-
/// let expected_payment_id = payment_id;
2083-
/// assert!(
2084-
/// channel_manager.list_recent_payments().iter().find(|details| matches!(
2085-
/// details,
2086-
/// RecentPaymentDetails::AwaitingInvoice { payment_id: expected_payment_id }
2087-
/// )).is_some()
2088-
/// );
2089-
///
2090-
/// // Once the invoice is received, a payment will be sent
2091-
/// assert!(
2092-
/// channel_manager.list_recent_payments().iter().find(|details| matches!(
2093-
/// details,
2094-
/// RecentPaymentDetails::Pending { payment_id: expected_payment_id, .. }
2095-
/// )).is_some()
2096-
/// );
2097-
///
2098-
/// // On the event processing thread
2099-
/// channel_manager.process_pending_events(&|event| {
2100-
/// match event {
2101-
/// Event::PaymentSent { payment_id: Some(payment_id), .. } => println!("Paid {}", payment_id),
2102-
/// Event::PaymentFailed { payment_id, .. } => println!("Failed paying {}", payment_id),
2103-
/// // ...
2104-
/// # _ => {},
2105-
/// }
2106-
/// Ok(())
2107-
/// });
2108-
/// # Ok(())
2109-
/// # }
2110-
/// ```
2111-
///
21122051
/// Use [`request_refund_payment`] to send a [`Bolt12Invoice`] for receiving the refund. Similar to
21132052
/// *creating* an [`Offer`], this is stateless as it represents an inbound payment.
21142053
///
@@ -2235,7 +2174,6 @@ where
22352174
/// [`offers`]: crate::offers
22362175
/// [`pay_for_offer`]: Self::pay_for_offer
22372176
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
2238-
/// [`create_refund_builder`]: Self::create_refund_builder
22392177
/// [`request_refund_payment`]: Self::request_refund_payment
22402178
/// [`peer_disconnected`]: msgs::ChannelMessageHandler::peer_disconnected
22412179
/// [`funding_created`]: msgs::FundingCreated
@@ -2734,12 +2672,14 @@ const MAX_NO_CHANNEL_PEERS: usize = 250;
27342672
/// The maximum expiration from the current time where an [`Offer`] or [`Refund`] is considered
27352673
/// short-lived, while anything with a greater expiration is considered long-lived.
27362674
///
2737-
/// Using [`OffersMessageFlow::create_offer_builder`] or [`ChannelManager::create_refund_builder`],
2675+
/// Using [`OffersMessageFlow::create_offer_builder`] or [`OffersMessageFlow::create_refund_builder`],
27382676
/// will included a [`BlindedMessagePath`] created using:
27392677
/// - [`MessageRouter::create_compact_blinded_paths`] when short-lived, and
27402678
/// - [`MessageRouter::create_blinded_paths`] when long-lived.
27412679
///
27422680
/// [`OffersMessageFlow::create_offer_builder`]: crate::offers::flow::OffersMessageFlow::create_offer_builder
2681+
/// [`OffersMessageFlow::create_refund_builder`]: crate::offers::flow::OffersMessageFlow::create_refund_builder
2682+
///
27432683
///
27442684
/// Using compact [`BlindedMessagePath`]s may provide better privacy as the [`MessageRouter`] could select
27452685
/// more hops. However, since they use short channel ids instead of pubkeys, they are more likely to
@@ -3609,45 +3549,6 @@ where
36093549
vec![]
36103550
}
36113551

3612-
/// Returns in an undefined order recent payments that -- if not fulfilled -- have yet to find a
3613-
/// successful path, or have unresolved HTLCs.
3614-
///
3615-
/// This can be useful for payments that may have been prepared, but ultimately not sent, as a
3616-
/// result of a crash. If such a payment exists, is not listed here, and an
3617-
/// [`Event::PaymentSent`] has not been received, you may consider resending the payment.
3618-
///
3619-
/// [`Event::PaymentSent`]: events::Event::PaymentSent
3620-
pub fn list_recent_payments(&self) -> Vec<RecentPaymentDetails> {
3621-
self.pending_outbound_payments.pending_outbound_payments.lock().unwrap().iter()
3622-
.filter_map(|(payment_id, pending_outbound_payment)| match pending_outbound_payment {
3623-
PendingOutboundPayment::AwaitingInvoice { .. }
3624-
| PendingOutboundPayment::AwaitingOffer { .. }
3625-
// InvoiceReceived is an intermediate state and doesn't need to be exposed
3626-
| PendingOutboundPayment::InvoiceReceived { .. } =>
3627-
{
3628-
Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id })
3629-
},
3630-
PendingOutboundPayment::StaticInvoiceReceived { .. } => {
3631-
Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id })
3632-
},
3633-
PendingOutboundPayment::Retryable { payment_hash, total_msat, .. } => {
3634-
Some(RecentPaymentDetails::Pending {
3635-
payment_id: *payment_id,
3636-
payment_hash: *payment_hash,
3637-
total_msat: *total_msat,
3638-
})
3639-
},
3640-
PendingOutboundPayment::Abandoned { payment_hash, .. } => {
3641-
Some(RecentPaymentDetails::Abandoned { payment_id: *payment_id, payment_hash: *payment_hash })
3642-
},
3643-
PendingOutboundPayment::Fulfilled { payment_hash, .. } => {
3644-
Some(RecentPaymentDetails::Fulfilled { payment_id: *payment_id, payment_hash: *payment_hash })
3645-
},
3646-
PendingOutboundPayment::Legacy { .. } => None
3647-
})
3648-
.collect()
3649-
}
3650-
36513552
fn close_channel_internal(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, target_feerate_sats_per_1000_weight: Option<u32>, override_shutdown_script: Option<ShutdownScript>) -> Result<(), APIError> {
36523553
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
36533554

@@ -9308,87 +9209,6 @@ impl Default for Bolt11InvoiceParameters {
93089209
}
93099210
}
93109211

9311-
macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
9312-
/// Creates a [`RefundBuilder`] such that the [`Refund`] it builds is recognized by the
9313-
/// [`ChannelManager`] when handling [`Bolt12Invoice`] messages for the refund.
9314-
///
9315-
/// # Payment
9316-
///
9317-
/// The provided `payment_id` is used to ensure that only one invoice is paid for the refund.
9318-
/// See [Avoiding Duplicate Payments] for other requirements once the payment has been sent.
9319-
///
9320-
/// The builder will have the provided expiration set. Any changes to the expiration on the
9321-
/// returned builder will not be honored by [`ChannelManager`]. For non-`std`, the highest seen
9322-
/// block time minus two hours is used for the current time when determining if the refund has
9323-
/// expired.
9324-
///
9325-
/// To revoke the refund, use [`ChannelManager::abandon_payment`] prior to receiving the
9326-
/// invoice. If abandoned, or an invoice isn't received before expiration, the payment will fail
9327-
/// with an [`Event::PaymentFailed`].
9328-
///
9329-
/// If `max_total_routing_fee_msat` is not specified, The default from
9330-
/// [`RouteParameters::from_payment_params_and_value`] is applied.
9331-
///
9332-
/// # Privacy
9333-
///
9334-
/// Uses [`MessageRouter`] to construct a [`BlindedMessagePath`] for the refund based on the given
9335-
/// `absolute_expiry` according to [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`]. See those docs for
9336-
/// privacy implications as well as those of the parameterized [`Router`], which implements
9337-
/// [`MessageRouter`].
9338-
///
9339-
/// Also, uses a derived payer id in the refund for payer privacy.
9340-
///
9341-
/// # Limitations
9342-
///
9343-
/// Requires a direct connection to an introduction node in the responding
9344-
/// [`Bolt12Invoice::payment_paths`].
9345-
///
9346-
/// # Errors
9347-
///
9348-
/// Errors if:
9349-
/// - a duplicate `payment_id` is provided given the caveats in the aforementioned link,
9350-
/// - `amount_msats` is invalid, or
9351-
/// - the parameterized [`Router`] is unable to create a blinded path for the refund.
9352-
///
9353-
/// [`Refund`]: crate::offers::refund::Refund
9354-
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
9355-
/// [`Bolt12Invoice::payment_paths`]: crate::offers::invoice::Bolt12Invoice::payment_paths
9356-
/// [Avoiding Duplicate Payments]: #avoiding-duplicate-payments
9357-
pub fn create_refund_builder(
9358-
&$self, amount_msats: u64, absolute_expiry: Duration, payment_id: PaymentId,
9359-
retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>
9360-
) -> Result<$builder, Bolt12SemanticError> {
9361-
let node_id = $self.get_our_node_id();
9362-
let expanded_key = &$self.inbound_payment_key;
9363-
let entropy = &*$self.entropy_source;
9364-
let secp_ctx = &$self.secp_ctx;
9365-
9366-
let nonce = Nonce::from_entropy_source(entropy);
9367-
let context = OffersContext::OutboundPayment { payment_id, nonce, hmac: None };
9368-
let path = $self.create_blinded_paths_using_absolute_expiry(context, Some(absolute_expiry))
9369-
.and_then(|paths| paths.into_iter().next().ok_or(()))
9370-
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
9371-
9372-
let builder = RefundBuilder::deriving_signing_pubkey(
9373-
node_id, expanded_key, nonce, secp_ctx, amount_msats, payment_id
9374-
)?
9375-
.chain_hash($self.chain_hash)
9376-
.absolute_expiry(absolute_expiry)
9377-
.path(path);
9378-
9379-
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop($self);
9380-
9381-
let expiration = StaleExpiration::AbsoluteTimeout(absolute_expiry);
9382-
$self.pending_outbound_payments
9383-
.add_new_awaiting_invoice(
9384-
payment_id, expiration, retry_strategy, max_total_routing_fee_msat, None,
9385-
)
9386-
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
9387-
9388-
Ok(builder.into())
9389-
}
9390-
} }
9391-
93929212
/// Functions commonly shared in usage between [`ChannelManager`] & [`OffersMessageFlow`]
93939213
///
93949214
/// [`OffersMessageFlow`]: crate::offers::flow::OffersMessageFlow
@@ -9515,6 +9335,19 @@ pub trait OffersMessageCommons {
95159335
/// [`create_inbound_payment_for_hash`]: ChannelManager::create_inbound_payment_for_hash
95169336
/// [`claim_funds_with_known_custom_tlvs`]: ChannelManager::claim_funds_with_known_custom_tlvs
95179337
fn claim_funds(&self, payment_preimage: PaymentPreimage);
9338+
9339+
/// Add new awaiting invoice
9340+
fn add_new_awaiting_invoice(&self, payment_id: PaymentId, expiration: StaleExpiration, retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>, retryable_invoice_request: Option<RetryableInvoiceRequest>) -> Result<(), ()>;
9341+
9342+
/// Returns in an undefined order recent payments that -- if not fulfilled -- have yet to find a
9343+
/// successful path, or have unresolved HTLCs.
9344+
///
9345+
/// This can be useful for payments that may have been prepared, but ultimately not sent, as a
9346+
/// result of a crash. If such a payment exists, is not listed here, and an
9347+
/// [`Event::PaymentSent`] has not been received, you may consider resending the payment.
9348+
///
9349+
/// [`Event::PaymentSent`]: events::Event::PaymentSent
9350+
fn list_recent_payments(&self) -> Vec<RecentPaymentDetails>;
95189351
}
95199352

95209353
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, MR: Deref, L: Deref> OffersMessageCommons for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
@@ -9690,6 +9523,44 @@ where
96909523
fn claim_funds(&self, payment_preimage: PaymentPreimage) {
96919524
self.claim_payment_internal(payment_preimage, false);
96929525
}
9526+
9527+
fn add_new_awaiting_invoice(&self, payment_id: PaymentId, expiration: StaleExpiration, retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>, retryable_invoice_request: Option<RetryableInvoiceRequest>) -> Result<(), ()> {
9528+
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
9529+
self.pending_outbound_payments.add_new_awaiting_invoice (
9530+
payment_id, expiration, retry_strategy, max_total_routing_fee_msat, retryable_invoice_request,
9531+
)
9532+
}
9533+
9534+
fn list_recent_payments(&self) -> Vec<RecentPaymentDetails> {
9535+
self.pending_outbound_payments.pending_outbound_payments.lock().unwrap().iter()
9536+
.filter_map(|(payment_id, pending_outbound_payment)| match pending_outbound_payment {
9537+
PendingOutboundPayment::AwaitingInvoice { .. }
9538+
| PendingOutboundPayment::AwaitingOffer { .. }
9539+
// InvoiceReceived is an intermediate state and doesn't need to be exposed
9540+
| PendingOutboundPayment::InvoiceReceived { .. } =>
9541+
{
9542+
Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id })
9543+
},
9544+
PendingOutboundPayment::StaticInvoiceReceived { .. } => {
9545+
Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id })
9546+
},
9547+
PendingOutboundPayment::Retryable { payment_hash, total_msat, .. } => {
9548+
Some(RecentPaymentDetails::Pending {
9549+
payment_id: *payment_id,
9550+
payment_hash: *payment_hash,
9551+
total_msat: *total_msat,
9552+
})
9553+
},
9554+
PendingOutboundPayment::Abandoned { payment_hash, .. } => {
9555+
Some(RecentPaymentDetails::Abandoned { payment_id: *payment_id, payment_hash: *payment_hash })
9556+
},
9557+
PendingOutboundPayment::Fulfilled { payment_hash, .. } => {
9558+
Some(RecentPaymentDetails::Fulfilled { payment_id: *payment_id, payment_hash: *payment_hash })
9559+
},
9560+
PendingOutboundPayment::Legacy { .. } => None
9561+
})
9562+
.collect()
9563+
}
96939564
}
96949565

96959566
/// Defines the maximum number of [`OffersMessage`] including different reply paths to be sent
@@ -9711,12 +9582,6 @@ where
97119582
MR::Target: MessageRouter,
97129583
L::Target: Logger,
97139584
{
9714-
#[cfg(not(c_bindings))]
9715-
create_refund_builder!(self, RefundBuilder<secp256k1::All>);
9716-
9717-
#[cfg(c_bindings)]
9718-
create_refund_builder!(self, RefundMaybeWithDerivedMetadataBuilder);
9719-
97209585
/// Pays for an [`Offer`] using the given parameters by creating an [`InvoiceRequest`] and
97219586
/// enqueuing it to be sent via an onion message. [`ChannelManager`] will pay the actual
97229587
/// [`Bolt12Invoice`] once it is received.

0 commit comments

Comments
 (0)