Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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} => (),
);
18 changes: 9 additions & 9 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 @@ -988,7 +988,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 @@ -1073,7 +1073,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 @@ -1144,7 +1144,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 @@ -2384,7 +2384,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 @@ -2719,7 +2719,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 @@ -2962,7 +2962,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 @@ -3199,7 +3199,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 @@ -3449,5 +3449,5 @@ 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));
}
2 changes: 2 additions & 0 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16535,6 +16535,7 @@ mod tests {
first_hop_htlc_msat: 548,
payment_id: PaymentId([42; 32]),
bolt12_invoice: None,
payment_nonce: None,
},
skimmed_fee_msat: None,
blinding_point: None,
Expand Down Expand Up @@ -16986,6 +16987,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