Skip to content
1 change: 1 addition & 0 deletions fuzz/src/process_onion_failure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
first_hop_htlc_msat: 0,
payment_id,
bolt12_invoice: None,
payment_nonce: None,
};

let failure_len = get_u16!();
Expand Down
47 changes: 19 additions & 28 deletions lightning/src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ use crate::ln::outbound_payment::RecipientOnionFields;
use crate::ln::types::ChannelId;
use crate::offers::invoice::Bolt12Invoice;
use crate::offers::invoice_request::InvoiceRequest;
use crate::offers::nonce::Nonce;
use crate::offers::payer_proof::Bolt12InvoiceType;
pub use crate::offers::payer_proof::PaidBolt12Invoice;
use crate::offers::static_invoice::StaticInvoice;
use crate::onion_message::messenger::Responder;
use crate::routing::gossip::NetworkUpdate;
Expand Down Expand Up @@ -1089,17 +1092,13 @@ pub enum Event {
///
/// [`Route::get_total_fees`]: crate::routing::router::Route::get_total_fees
fee_paid_msat: Option<u64>,
/// The BOLT 12 invoice that was paid. `None` if the payment was a non BOLT 12 payment.
/// The paid BOLT 12 invoice bundled with the data needed to construct a
/// [`PayerProof`], which selectively discloses invoice fields to prove payment to a
/// third party.
///
/// The BOLT 12 invoice is useful for proof of payment because it contains the
/// payment hash. A third party can verify that the payment was made by
/// showing the invoice and confirming that the payment hash matches
/// the hash of the payment preimage.
/// `None` for non-BOLT 12 payments.
///
/// However, the [`PaidBolt12Invoice`] can also be of type [`StaticInvoice`], which
/// is a special [`Bolt12Invoice`] where proof of payment is not possible.
///
/// [`StaticInvoice`]: crate::offers::static_invoice::StaticInvoice
/// [`PayerProof`]: crate::offers::payer_proof::PayerProof
bolt12_invoice: Option<PaidBolt12Invoice>,
},
/// Indicates an outbound payment failed. Individual [`Event::PaymentPathFailed`] events
Expand Down Expand Up @@ -1975,13 +1974,16 @@ impl Writeable for Event {
ref bolt12_invoice,
} => {
2u8.write(writer)?;
let invoice_type = bolt12_invoice.as_ref().map(|paid| paid.invoice_type());
let payment_nonce = bolt12_invoice.as_ref().and_then(|paid| paid.nonce());
write_tlv_fields!(writer, {
(0, payment_preimage, required),
(1, payment_hash, required),
(3, payment_id, option),
(5, fee_paid_msat, option),
(7, amount_msat, option),
(9, bolt12_invoice, option),
(9, invoice_type, option),
(11, payment_nonce, option),
});
},
&Event::PaymentPathFailed {
Expand Down Expand Up @@ -2473,20 +2475,25 @@ impl MaybeReadable for Event {
let mut payment_id = None;
let mut amount_msat = None;
let mut fee_paid_msat = None;
let mut bolt12_invoice = None;
let mut invoice_type: Option<Bolt12InvoiceType> = None;
let mut payment_nonce: Option<Nonce> = None;
read_tlv_fields!(reader, {
(0, payment_preimage, required),
(1, payment_hash, option),
(3, payment_id, option),
(5, fee_paid_msat, option),
(7, amount_msat, option),
(9, bolt12_invoice, option),
(9, invoice_type, option),
(11, payment_nonce, option),
});
if payment_hash.is_none() {
payment_hash = Some(PaymentHash(
Sha256::hash(&payment_preimage.0[..]).to_byte_array(),
));
}
let bolt12_invoice = invoice_type.map(|invoice| {
PaidBolt12Invoice::new(invoice, payment_preimage, payment_nonce)
});
Ok(Some(Event::PaymentSent {
payment_id,
payment_preimage,
Expand Down Expand Up @@ -3146,19 +3153,3 @@ impl<T: EventHandler> EventHandler for Arc<T> {
self.deref().handle_event(event)
}
}

/// The BOLT 12 invoice that was paid, surfaced in [`Event::PaymentSent::bolt12_invoice`].
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum PaidBolt12Invoice {
/// The BOLT 12 invoice specified by the BOLT 12 specification,
/// allowing the user to perform proof of payment.
Bolt12Invoice(Bolt12Invoice),
/// The Static invoice, used in the async payment specification update proposal,
/// where the user cannot perform proof of payment.
StaticInvoice(StaticInvoice),
}

impl_writeable_tlv_based_enum!(PaidBolt12Invoice,
{0, Bolt12Invoice} => (),
{2, StaticInvoice} => (),
);
20 changes: 10 additions & 10 deletions lightning/src/ln/async_payments_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::blinded_path::payment::{AsyncBolt12OfferContext, BlindedPaymentTlvs};
use crate::blinded_path::payment::{DummyTlvs, PaymentContext};
use crate::chain::channelmonitor::{HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
use crate::events::{
Event, EventsProvider, HTLCHandlingFailureReason, HTLCHandlingFailureType, PaidBolt12Invoice,
Event, EventsProvider, HTLCHandlingFailureReason, HTLCHandlingFailureType,
PaymentFailureReason, PaymentPurpose,
};
use crate::ln::blinded_payment_tests::{fail_blinded_htlc_backwards, get_blinded_route_parameters};
Expand Down Expand Up @@ -991,7 +991,7 @@ fn ignore_duplicate_invoice() {
let keysend_preimage = extract_payment_preimage(&claimable_ev);
let (res, _) =
claim_payment_along_route(ClaimAlongRouteArgs::new(sender, route, keysend_preimage));
assert_eq!(res, Some(PaidBolt12Invoice::StaticInvoice(static_invoice.clone())));
assert_eq!(res.as_ref().and_then(|paid| paid.static_invoice()), Some(&static_invoice));

// After paying the static invoice, check that regular invoice received from async recipient is ignored.
match sender.onion_messenger.peel_onion_message(&invoice_om) {
Expand Down Expand Up @@ -1076,7 +1076,7 @@ fn ignore_duplicate_invoice() {

// After paying invoice, check that static invoice is ignored.
let res = claim_payment(sender, route[0], payment_preimage);
assert_eq!(res, Some(PaidBolt12Invoice::Bolt12Invoice(invoice)));
assert_eq!(res.as_ref().and_then(|paid| paid.bolt12_invoice()), Some(&invoice));

sender.onion_messenger.handle_onion_message(always_online_node_id, &static_invoice_om);
let async_pmts_msgs = AsyncPaymentsMessageHandler::release_pending_messages(sender.node);
Expand Down Expand Up @@ -1147,7 +1147,7 @@ fn async_receive_flow_success() {
let keysend_preimage = extract_payment_preimage(&claimable_ev);
let (res, _) =
claim_payment_along_route(ClaimAlongRouteArgs::new(&nodes[0], route, keysend_preimage));
assert_eq!(res, Some(PaidBolt12Invoice::StaticInvoice(static_invoice)));
assert_eq!(res.as_ref().and_then(|paid| paid.static_invoice()), Some(&static_invoice));
}

#[cfg_attr(feature = "std", ignore)]
Expand Down Expand Up @@ -2390,7 +2390,7 @@ fn refresh_static_invoices_for_used_offers() {
let claimable_ev = do_pass_along_path(args).unwrap();
let keysend_preimage = extract_payment_preimage(&claimable_ev);
let res = claim_payment_along_route(ClaimAlongRouteArgs::new(sender, route, keysend_preimage));
assert_eq!(res.0, Some(PaidBolt12Invoice::StaticInvoice(updated_invoice)));
assert_eq!(res.0.as_ref().and_then(|paid| paid.static_invoice()), Some(&updated_invoice));
}

#[cfg_attr(feature = "std", ignore)]
Expand Down Expand Up @@ -2725,7 +2725,7 @@ fn invoice_server_is_not_channel_peer() {
let claimable_ev = do_pass_along_path(args).unwrap();
let keysend_preimage = extract_payment_preimage(&claimable_ev);
let res = claim_payment_along_route(ClaimAlongRouteArgs::new(sender, route, keysend_preimage));
assert_eq!(res.0, Some(PaidBolt12Invoice::StaticInvoice(invoice)));
assert_eq!(res.0.as_ref().and_then(|paid| paid.static_invoice()), Some(&invoice));
}

#[test]
Expand Down Expand Up @@ -2968,7 +2968,7 @@ fn async_payment_e2e() {
let keysend_preimage = extract_payment_preimage(&claimable_ev);
let (res, _) =
claim_payment_along_route(ClaimAlongRouteArgs::new(sender, route, keysend_preimage));
assert_eq!(res, Some(PaidBolt12Invoice::StaticInvoice(static_invoice)));
assert_eq!(res.as_ref().and_then(|paid| paid.static_invoice()), Some(&static_invoice));
}

#[test]
Expand Down Expand Up @@ -3205,7 +3205,7 @@ fn intercepted_hold_htlc() {
let keysend_preimage = extract_payment_preimage(&claimable_ev);
let (res, _) =
claim_payment_along_route(ClaimAlongRouteArgs::new(sender, route, keysend_preimage));
assert_eq!(res, Some(PaidBolt12Invoice::StaticInvoice(static_invoice)));
assert_eq!(res.as_ref().and_then(|paid| paid.static_invoice()), Some(&static_invoice));
}

#[test]
Expand Down Expand Up @@ -3455,7 +3455,7 @@ fn release_htlc_races_htlc_onion_decode() {
let keysend_preimage = extract_payment_preimage(&claimable_ev);
let (res, _) =
claim_payment_along_route(ClaimAlongRouteArgs::new(sender, route, keysend_preimage));
assert_eq!(res, Some(PaidBolt12Invoice::StaticInvoice(static_invoice)));
assert_eq!(res.as_ref().and_then(|paid| paid.static_invoice()), Some(&static_invoice));
}

#[test]
Expand Down Expand Up @@ -3619,5 +3619,5 @@ fn async_payment_e2e_release_before_hold_registered() {
let keysend_preimage = extract_payment_preimage(&claimable_ev);
let (res, _) =
claim_payment_along_route(ClaimAlongRouteArgs::new(sender, route, keysend_preimage));
assert_eq!(res, Some(PaidBolt12Invoice::StaticInvoice(static_invoice)));
assert_eq!(res.as_ref().and_then(|paid| paid.static_invoice()), Some(&static_invoice));
}
2 changes: 2 additions & 0 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17081,6 +17081,7 @@ mod tests {
first_hop_htlc_msat: 548,
payment_id: PaymentId([42; 32]),
bolt12_invoice: None,
payment_nonce: None,
Comment thread
vincenzopalazzo marked this conversation as resolved.
},
skimmed_fee_msat: None,
blinding_point: None,
Expand Down Expand Up @@ -17574,6 +17575,7 @@ mod tests {
first_hop_htlc_msat: 0,
payment_id: PaymentId([42; 32]),
bolt12_invoice: None,
payment_nonce: None,
};
let dummy_outbound_output = OutboundHTLCOutput {
htlc_id: 0,
Expand Down
Loading
Loading