Skip to content

Commit ffe3d6d

Browse files
add the bolt12 invoice to the PaymentSend event
This commit make two things possible: 1. make persistent BOLT12 invoice through PendingOutboundPayment This commit prepares the code to pass down the BOLT12 invoice inside the `PaymentSent` event. To achieve this, the `bolt12` field has been added to the `PendingOutboundPayment::Retryable` enum, allowing it to be attached to the `PaymentSent` event when the payment is completed. 2. To enable proof of payment, we need to share the bolt12 invoice with the library user. This is already possible if we `manually_handle_bolt12_invoices`, but this approach requires a significant amount of work from the user. This commit adds the bolt12 invoice to the PaymentSend event when the payment is completed. This allows the user to always have the option to perform proof of payment. Link: lightningdevkit#3344 Signed-off-by: Vincenzo Palazzo <[email protected]>
1 parent f80cd8d commit ffe3d6d

File tree

5 files changed

+119
-50
lines changed

5 files changed

+119
-50
lines changed

lightning/src/events/mod.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,17 @@ pub enum Event {
949949
///
950950
/// [`Route::get_total_fees`]: crate::routing::router::Route::get_total_fees
951951
fee_paid_msat: Option<u64>,
952+
/// The BOLT 12 invoice that was paid. `None` if the payment was a non BOLT 12 payment.
953+
///
954+
/// The BOLT 12 invoice is useful for proof of payment because it contains the
955+
/// payment hash. A third party can verify that the payment was made by
956+
/// showing the invoice and confirming that the payment hash matches
957+
/// the hash of the payment preimage.
958+
///
959+
/// However, the [`PaidInvoice`] can also be of type [`StaticInvoice`], which
960+
/// is a special [`Bolt12Invoice`] where proof of payment is not possible.
961+
/// For more details, see the `async_payments` specification.
962+
bolt12_invoice: Option<PaidInvoice>,
952963
},
953964
/// Indicates an outbound payment failed. Individual [`Event::PaymentPathFailed`] events
954965
/// provide failure information for each path attempt in the payment, including retries.
@@ -1556,14 +1567,15 @@ impl Writeable for Event {
15561567
(13, payment_id, option),
15571568
});
15581569
},
1559-
&Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref amount_msat, ref fee_paid_msat } => {
1570+
&Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref amount_msat, ref fee_paid_msat, ref bolt12_invoice } => {
15601571
2u8.write(writer)?;
15611572
write_tlv_fields!(writer, {
15621573
(0, payment_preimage, required),
15631574
(1, payment_hash, required),
15641575
(3, payment_id, option),
15651576
(5, fee_paid_msat, option),
15661577
(7, amount_msat, option),
1578+
(9, bolt12_invoice, option),
15671579
});
15681580
},
15691581
&Event::PaymentPathFailed {
@@ -1898,12 +1910,14 @@ impl MaybeReadable for Event {
18981910
let mut payment_id = None;
18991911
let mut amount_msat = None;
19001912
let mut fee_paid_msat = None;
1913+
let mut bolt12_invoice = None;
19011914
read_tlv_fields!(reader, {
19021915
(0, payment_preimage, required),
19031916
(1, payment_hash, option),
19041917
(3, payment_id, option),
19051918
(5, fee_paid_msat, option),
19061919
(7, amount_msat, option),
1920+
(9, bolt12_invoice, option),
19071921
});
19081922
if payment_hash.is_none() {
19091923
payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()));
@@ -1914,6 +1928,7 @@ impl MaybeReadable for Event {
19141928
payment_hash: payment_hash.unwrap(),
19151929
amount_msat,
19161930
fee_paid_msat,
1931+
bolt12_invoice,
19171932
}))
19181933
};
19191934
f()
@@ -2438,3 +2453,17 @@ impl<T: EventHandler> EventHandler for Arc<T> {
24382453
self.deref().handle_event(event)
24392454
}
24402455
}
2456+
2457+
/// The BOLT 12 invoice that was paid, surfaced in [`Event::PaymentSent::bolt12_invoice`].
2458+
#[derive(Clone, Debug, PartialEq, Eq)]
2459+
pub enum PaidInvoice {
2460+
///
2461+
Bolt12Invoice(crate::offers::invoice::Bolt12Invoice),
2462+
///
2463+
StaticInvoice(crate::offers::static_invoice::StaticInvoice),
2464+
}
2465+
2466+
impl_writeable_tlv_based_enum!(PaidInvoice,
2467+
{0, Bolt12Invoice} => (),
2468+
{2, StaticInvoice} => (),
2469+
);

lightning/src/ln/functional_test_utils.rs

+17-10
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use crate::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen, Watch, chainmonitor::Persist};
1414
use crate::chain::channelmonitor::ChannelMonitor;
1515
use crate::chain::transaction::OutPoint;
16-
use crate::events::{ClaimedHTLC, ClosureReason, Event, HTLCDestination, PathFailure, PaymentPurpose, PaymentFailureReason};
16+
use crate::events::{ClaimedHTLC, ClosureReason, Event, HTLCDestination, PaidInvoice, PathFailure, PaymentFailureReason, PaymentPurpose};
1717
use crate::events::bump_transaction::{BumpTransactionEvent, BumpTransactionEventHandler, Wallet, WalletSource};
1818
use crate::ln::types::ChannelId;
1919
use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret};
@@ -2294,7 +2294,7 @@ macro_rules! expect_payment_claimed {
22942294
pub fn expect_payment_sent<CM: AChannelManager, H: NodeHolder<CM=CM>>(node: &H,
22952295
expected_payment_preimage: PaymentPreimage, expected_fee_msat_opt: Option<Option<u64>>,
22962296
expect_per_path_claims: bool, expect_post_ev_mon_update: bool,
2297-
) {
2297+
) -> Option<PaidInvoice> {
22982298
let events = node.node().get_and_clear_pending_events();
22992299
let expected_payment_hash = PaymentHash(
23002300
bitcoin::hashes::sha256::Hash::hash(&expected_payment_preimage.0).to_byte_array());
@@ -2306,8 +2306,11 @@ pub fn expect_payment_sent<CM: AChannelManager, H: NodeHolder<CM=CM>>(node: &H,
23062306
if expect_post_ev_mon_update {
23072307
check_added_monitors(node, 1);
23082308
}
2309+
// We return the invoice because some test may want to check the invoice details.
2310+
#[allow(unused_assignments)]
2311+
let mut invoice = None;
23092312
let expected_payment_id = match events[0] {
2310-
Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref amount_msat, ref fee_paid_msat } => {
2313+
Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref amount_msat, ref fee_paid_msat, ref bolt12_invoice } => {
23112314
assert_eq!(expected_payment_preimage, *payment_preimage);
23122315
assert_eq!(expected_payment_hash, *payment_hash);
23132316
assert!(amount_msat.is_some());
@@ -2316,6 +2319,7 @@ pub fn expect_payment_sent<CM: AChannelManager, H: NodeHolder<CM=CM>>(node: &H,
23162319
} else {
23172320
assert!(fee_paid_msat.is_some());
23182321
}
2322+
invoice = bolt12_invoice.clone();
23192323
payment_id.unwrap()
23202324
},
23212325
_ => panic!("Unexpected event"),
@@ -2331,19 +2335,20 @@ pub fn expect_payment_sent<CM: AChannelManager, H: NodeHolder<CM=CM>>(node: &H,
23312335
}
23322336
}
23332337
}
2338+
invoice
23342339
}
23352340

23362341
#[macro_export]
23372342
macro_rules! expect_payment_sent {
23382343
($node: expr, $expected_payment_preimage: expr) => {
2339-
$crate::expect_payment_sent!($node, $expected_payment_preimage, None::<u64>, true);
2344+
$crate::expect_payment_sent!($node, $expected_payment_preimage, None::<u64>, true)
23402345
};
23412346
($node: expr, $expected_payment_preimage: expr, $expected_fee_msat_opt: expr) => {
2342-
$crate::expect_payment_sent!($node, $expected_payment_preimage, $expected_fee_msat_opt, true);
2347+
$crate::expect_payment_sent!($node, $expected_payment_preimage, $expected_fee_msat_opt, true)
23432348
};
23442349
($node: expr, $expected_payment_preimage: expr, $expected_fee_msat_opt: expr, $expect_paths: expr) => {
23452350
$crate::ln::functional_test_utils::expect_payment_sent(&$node, $expected_payment_preimage,
2346-
$expected_fee_msat_opt.map(|o| Some(o)), $expect_paths, true);
2351+
$expected_fee_msat_opt.map(|o| Some(o)), $expect_paths, true)
23472352
}
23482353
}
23492354

@@ -3106,20 +3111,22 @@ pub fn pass_claimed_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
31063111

31073112
expected_total_fee_msat
31083113
}
3109-
pub fn claim_payment_along_route(args: ClaimAlongRouteArgs) {
3114+
pub fn claim_payment_along_route(args: ClaimAlongRouteArgs) -> Option<PaidInvoice> {
31103115
let origin_node = args.origin_node;
31113116
let payment_preimage = args.payment_preimage;
31123117
let skip_last = args.skip_last;
31133118
let expected_total_fee_msat = do_claim_payment_along_route(args);
31143119
if !skip_last {
3115-
expect_payment_sent!(origin_node, payment_preimage, Some(expected_total_fee_msat));
3120+
expect_payment_sent!(origin_node, payment_preimage, Some(expected_total_fee_msat))
3121+
} else {
3122+
None
31163123
}
31173124
}
31183125

3119-
pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage) {
3126+
pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage) -> Option<PaidInvoice> {
31203127
claim_payment_along_route(
31213128
ClaimAlongRouteArgs::new(origin_node, &[expected_route], our_payment_preimage)
3122-
);
3129+
)
31233130
}
31243131

31253132
pub const TEST_FINAL_CLTV: u32 = 70;

lightning/src/ln/offers_tests.rs

+16-12
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ fn route_bolt12_payment<'a, 'b, 'c>(
167167
}
168168

169169
fn claim_bolt12_payment<'a, 'b, 'c>(
170-
node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], expected_payment_context: PaymentContext
170+
node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], expected_payment_context: PaymentContext, invoice: &Bolt12Invoice
171171
) {
172172
let recipient = &path[path.len() - 1];
173173
let payment_purpose = match get_event!(recipient, Event::PaymentClaimable) {
@@ -187,7 +187,11 @@ fn claim_bolt12_payment<'a, 'b, 'c>(
187187
},
188188
_ => panic!("Unexpected payment purpose: {:?}", payment_purpose),
189189
}
190-
claim_payment(node, path, payment_preimage);
190+
if let Some(inv) = claim_payment(node, path, payment_preimage) {
191+
assert_eq!(inv, PaidInvoice::Bolt12Invoice(invoice.to_owned()));
192+
} else {
193+
panic!("Expected PaidInvoice::Bolt12Invoice");
194+
};
191195
}
192196

193197
fn extract_offer_nonce<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage) -> Nonce {
@@ -591,7 +595,7 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() {
591595
route_bolt12_payment(david, &[charlie, bob, alice], &invoice);
592596
expect_recent_payment!(david, RecentPaymentDetails::Pending, payment_id);
593597

594-
claim_bolt12_payment(david, &[charlie, bob, alice], payment_context);
598+
claim_bolt12_payment(david, &[charlie, bob, alice], payment_context, &invoice);
595599
expect_recent_payment!(david, RecentPaymentDetails::Fulfilled, payment_id);
596600
}
597601

@@ -674,7 +678,7 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() {
674678
route_bolt12_payment(david, &[charlie, bob, alice], &invoice);
675679
expect_recent_payment!(david, RecentPaymentDetails::Pending, payment_id);
676680

677-
claim_bolt12_payment(david, &[charlie, bob, alice], payment_context);
681+
claim_bolt12_payment(david, &[charlie, bob, alice], payment_context, &invoice);
678682
expect_recent_payment!(david, RecentPaymentDetails::Fulfilled, payment_id);
679683
}
680684

@@ -741,7 +745,7 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() {
741745
route_bolt12_payment(bob, &[alice], &invoice);
742746
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
743747

744-
claim_bolt12_payment(bob, &[alice], payment_context);
748+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
745749
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
746750
}
747751

@@ -797,7 +801,7 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() {
797801
route_bolt12_payment(bob, &[alice], &invoice);
798802
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
799803

800-
claim_bolt12_payment(bob, &[alice], payment_context);
804+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
801805
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
802806
}
803807

@@ -851,7 +855,7 @@ fn pays_for_offer_without_blinded_paths() {
851855
route_bolt12_payment(bob, &[alice], &invoice);
852856
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
853857

854-
claim_bolt12_payment(bob, &[alice], payment_context);
858+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
855859
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
856860
}
857861

@@ -894,7 +898,7 @@ fn pays_for_refund_without_blinded_paths() {
894898
route_bolt12_payment(bob, &[alice], &invoice);
895899
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
896900

897-
claim_bolt12_payment(bob, &[alice], payment_context);
901+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
898902
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
899903
}
900904

@@ -1132,7 +1136,7 @@ fn creates_and_pays_for_offer_with_retry() {
11321136
}
11331137
route_bolt12_payment(bob, &[alice], &invoice);
11341138
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
1135-
claim_bolt12_payment(bob, &[alice], payment_context);
1139+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
11361140
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
11371141
}
11381142

@@ -1203,7 +1207,7 @@ fn pays_bolt12_invoice_asynchronously() {
12031207
route_bolt12_payment(bob, &[alice], &invoice);
12041208
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
12051209

1206-
claim_bolt12_payment(bob, &[alice], payment_context);
1210+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
12071211
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
12081212

12091213
assert_eq!(
@@ -1283,7 +1287,7 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() {
12831287
route_bolt12_payment(bob, &[alice], &invoice);
12841288
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
12851289

1286-
claim_bolt12_payment(bob, &[alice], payment_context);
1290+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
12871291
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
12881292
}
12891293

@@ -2139,7 +2143,7 @@ fn fails_paying_invoice_more_than_once() {
21392143
assert!(david.node.get_and_clear_pending_msg_events().is_empty());
21402144

21412145
// Complete paying the first invoice
2142-
claim_bolt12_payment(david, &[charlie, bob, alice], payment_context);
2146+
claim_bolt12_payment(david, &[charlie, bob, alice], payment_context, &invoice1);
21432147
expect_recent_payment!(david, RecentPaymentDetails::Fulfilled, payment_id);
21442148
}
21452149

0 commit comments

Comments
 (0)