pub use bump_transaction::BumpTransactionEvent;
+use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext, PaymentContextRef};
use crate::sign::SpendableOutputDescriptor;
use crate::ln::channelmanager::{InterceptId, PaymentId, RecipientOnionFields};
use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS;
/// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
payment_secret: PaymentSecret,
},
+ /// A payment for a BOLT 12 [`Offer`].
+ ///
+ /// [`Offer`]: crate::offers::offer::Offer
+ Bolt12OfferPayment {
+ /// The preimage to the payment hash. If provided, this can be handed directly to
+ /// [`ChannelManager::claim_funds`].
+ ///
+ /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
+ payment_preimage: Option<PaymentPreimage>,
+ /// The secret used to authenticate the sender to the recipient, preventing a number of
+ /// de-anonymization attacks while routing a payment.
+ ///
+ /// See [`PaymentPurpose::Bolt11InvoicePayment::payment_secret`] for further details.
+ payment_secret: PaymentSecret,
+ /// The context of the payment such as information about the corresponding [`Offer`] and
+ /// [`InvoiceRequest`].
+ ///
+ /// [`Offer`]: crate::offers::offer::Offer
+ /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
+ payment_context: Bolt12OfferContext,
+ },
+ /// A payment for a BOLT 12 [`Refund`].
+ ///
+ /// [`Refund`]: crate::offers::refund::Refund
+ Bolt12RefundPayment {
+ /// The preimage to the payment hash. If provided, this can be handed directly to
+ /// [`ChannelManager::claim_funds`].
+ ///
+ /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
+ payment_preimage: Option<PaymentPreimage>,
+ /// The secret used to authenticate the sender to the recipient, preventing a number of
+ /// de-anonymization attacks while routing a payment.
+ ///
+ /// See [`PaymentPurpose::Bolt11InvoicePayment::payment_secret`] for further details.
+ payment_secret: PaymentSecret,
+ /// The context of the payment such as information about the corresponding [`Refund`].
+ ///
+ /// [`Refund`]: crate::offers::refund::Refund
+ payment_context: Bolt12RefundContext,
+ },
/// Because this is a spontaneous payment, the payer generated their own preimage rather than us
/// (the payee) providing a preimage.
SpontaneousPayment(PaymentPreimage),
pub fn preimage(&self) -> Option<PaymentPreimage> {
match self {
PaymentPurpose::Bolt11InvoicePayment { payment_preimage, .. } => *payment_preimage,
+ PaymentPurpose::Bolt12OfferPayment { payment_preimage, .. } => *payment_preimage,
+ PaymentPurpose::Bolt12RefundPayment { payment_preimage, .. } => *payment_preimage,
PaymentPurpose::SpontaneousPayment(preimage) => Some(*preimage),
}
}
pub(crate) fn is_keysend(&self) -> bool {
match self {
PaymentPurpose::Bolt11InvoicePayment { .. } => false,
+ PaymentPurpose::Bolt12OfferPayment { .. } => false,
+ PaymentPurpose::Bolt12RefundPayment { .. } => false,
PaymentPurpose::SpontaneousPayment(..) => true,
}
}
(0, Bolt11InvoicePayment) => {
(0, payment_preimage, option),
(2, payment_secret, required),
- };
+ },
+ (4, Bolt12OfferPayment) => {
+ (0, payment_preimage, option),
+ (2, payment_secret, required),
+ (4, payment_context, required),
+ },
+ (6, Bolt12RefundPayment) => {
+ (0, payment_preimage, option),
+ (2, payment_secret, required),
+ (4, payment_context, required),
+ },
+ ;
(2, SpontaneousPayment)
);
1u8.write(writer)?;
let mut payment_secret = None;
let payment_preimage;
+ let mut payment_context = None;
match &purpose {
PaymentPurpose::Bolt11InvoicePayment {
payment_preimage: preimage, payment_secret: secret
payment_secret = Some(secret);
payment_preimage = *preimage;
},
+ PaymentPurpose::Bolt12OfferPayment {
+ payment_preimage: preimage, payment_secret: secret, payment_context: context
+ } => {
+ payment_secret = Some(secret);
+ payment_preimage = *preimage;
+ payment_context = Some(PaymentContextRef::Bolt12Offer(context));
+ },
+ PaymentPurpose::Bolt12RefundPayment {
+ payment_preimage: preimage, payment_secret: secret, payment_context: context
+ } => {
+ payment_secret = Some(secret);
+ payment_preimage = *preimage;
+ payment_context = Some(PaymentContextRef::Bolt12Refund(context));
+ },
PaymentPurpose::SpontaneousPayment(preimage) => {
payment_preimage = Some(*preimage);
}
(8, payment_preimage, option),
(9, onion_fields, option),
(10, skimmed_fee_opt, option),
+ (11, payment_context, option),
});
},
&Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref fee_paid_msat } => {
let mut claim_deadline = None;
let mut via_user_channel_id = None;
let mut onion_fields = None;
+ let mut payment_context = None;
read_tlv_fields!(reader, {
(0, payment_hash, required),
(1, receiver_node_id, option),
(8, payment_preimage, option),
(9, onion_fields, option),
(10, counterparty_skimmed_fee_msat_opt, option),
+ (11, payment_context, option),
});
let purpose = match payment_secret {
- Some(secret) => PaymentPurpose::Bolt11InvoicePayment {
- payment_preimage,
- payment_secret: secret
+ Some(secret) => match payment_context {
+ Some(PaymentContext::Unknown(_)) | None => {
+ PaymentPurpose::Bolt11InvoicePayment {
+ payment_preimage,
+ payment_secret: secret,
+ }
+ },
+ Some(PaymentContext::Bolt12Offer(context)) => {
+ PaymentPurpose::Bolt12OfferPayment {
+ payment_preimage,
+ payment_secret: secret,
+ payment_context: context,
+ }
+ },
+ Some(PaymentContext::Bolt12Refund(context)) => {
+ PaymentPurpose::Bolt12RefundPayment {
+ payment_preimage,
+ payment_secret: secret,
+ payment_context: context,
+ }
+ },
},
None if payment_preimage.is_some() => PaymentPurpose::SpontaneousPayment(payment_preimage.unwrap()),
None => return Err(msgs::DecodeError::InvalidValue),
/// println!("Claiming spontaneous payment {}", payment_hash);
/// channel_manager.claim_funds(payment_preimage);
/// },
+/// // ...
+/// # _ => {},
/// },
/// Event::PaymentClaimed { payment_hash, amount_msat, .. } => {
/// assert_eq!(payment_hash, known_payment_hash);
/// This differs from [`create_inbound_payment_for_hash`] only in that it generates the
/// [`PaymentHash`] and [`PaymentPreimage`] for you.
///
- /// The [`PaymentPreimage`] will ultimately be returned to you in the [`PaymentClaimable`], which
- /// will have the [`PaymentClaimable::purpose`] be [`PaymentPurpose::Bolt11InvoicePayment`] with
- /// its [`PaymentPurpose::Bolt11InvoicePayment::payment_preimage`] field filled in. That should
- /// then be passed directly to [`claim_funds`].
+ /// The [`PaymentPreimage`] will ultimately be returned to you in the [`PaymentClaimable`] event, which
+ /// will have the [`PaymentClaimable::purpose`] return `Some` for [`PaymentPurpose::preimage`]. That
+ /// should then be passed directly to [`claim_funds`].
///
/// See [`create_inbound_payment_for_hash`] for detailed documentation on behavior and requirements.
///
/// [`claim_funds`]: Self::claim_funds
/// [`PaymentClaimable`]: events::Event::PaymentClaimable
/// [`PaymentClaimable::purpose`]: events::Event::PaymentClaimable::purpose
- /// [`PaymentPurpose::Bolt11InvoicePayment`]: events::PaymentPurpose::Bolt11InvoicePayment
- /// [`PaymentPurpose::Bolt11InvoicePayment::payment_preimage`]: events::PaymentPurpose::Bolt11InvoicePayment::payment_preimage
+ /// [`PaymentPurpose::preimage`]: events::PaymentPurpose::preimage
/// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
pub fn create_inbound_payment(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32,
min_final_cltv_expiry_delta: Option<u16>) -> Result<(PaymentHash, PaymentSecret), ()> {
assert_eq!(&expected_payment_preimage, payment_preimage);
assert_eq!(expected_payment_secret, *payment_secret);
},
+ PaymentPurpose::Bolt12OfferPayment { payment_preimage, payment_secret, .. } => {
+ assert_eq!(&expected_payment_preimage, payment_preimage);
+ assert_eq!(expected_payment_secret, *payment_secret);
+ },
+ PaymentPurpose::Bolt12RefundPayment { payment_preimage, payment_secret, .. } => {
+ assert_eq!(&expected_payment_preimage, payment_preimage);
+ assert_eq!(expected_payment_secret, *payment_secret);
+ },
_ => {},
}
},
assert_eq!(our_payment_secret.unwrap(), *payment_secret);
assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);
},
+ PaymentPurpose::Bolt12OfferPayment { payment_preimage, payment_secret, .. } => {
+ assert_eq!(expected_preimage, *payment_preimage);
+ assert_eq!(our_payment_secret.unwrap(), *payment_secret);
+ assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);
+ },
+ PaymentPurpose::Bolt12RefundPayment { payment_preimage, payment_secret, .. } => {
+ assert_eq!(expected_preimage, *payment_preimage);
+ assert_eq!(our_payment_secret.unwrap(), *payment_secret);
+ assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret);
+ },
PaymentPurpose::SpontaneousPayment(payment_preimage) => {
assert_eq!(expected_preimage.unwrap(), *payment_preimage);
assert_eq!(our_payment_secret, onion_fields.as_ref().unwrap().payment_secret);
let mut fwd_amt_msat = 0;
match claim_event[0] {
Event::PaymentClaimed {
- purpose: PaymentPurpose::SpontaneousPayment(preimage),
+ purpose: PaymentPurpose::SpontaneousPayment(preimage)
+ | PaymentPurpose::Bolt11InvoicePayment { payment_preimage: Some(preimage), .. }
+ | PaymentPurpose::Bolt12OfferPayment { payment_preimage: Some(preimage), .. }
+ | PaymentPurpose::Bolt12RefundPayment { payment_preimage: Some(preimage), .. },
amount_msat,
ref htlcs,
- .. }
- | Event::PaymentClaimed {
- purpose: PaymentPurpose::Bolt11InvoicePayment { payment_preimage: Some(preimage), ..},
- ref htlcs,
- amount_msat,
..
} => {
assert_eq!(preimage, our_payment_preimage);
fwd_amt_msat = amount_msat;
},
Event::PaymentClaimed {
- purpose: PaymentPurpose::Bolt11InvoicePayment { .. },
+ purpose: PaymentPurpose::Bolt11InvoicePayment { .. }
+ | PaymentPurpose::Bolt12OfferPayment { .. }
+ | PaymentPurpose::Bolt12RefundPayment { .. },
payment_hash,
amount_msat,
ref htlcs,