Skip to content

Commit 99b4167

Browse files
add the bolt12 invoice to the PaymentSend event
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 85d807b commit 99b4167

File tree

4 files changed

+30
-14
lines changed

4 files changed

+30
-14
lines changed

lightning/src/events/mod.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,13 @@ pub enum Event {
949949
///
950950
/// [`Route::get_total_fees`]: crate::routing::router::Route::get_total_fees
951951
fee_paid_msat: Option<u64>,
952+
/// The bolt12 invoice that was paid. `None` if the payment was a non-bolt12 payment.
953+
///
954+
/// The bolt12 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+
bolt12_invoice: Option<Bolt12Invoice>,
952959
},
953960
/// Indicates an outbound payment failed. Individual [`Event::PaymentPathFailed`] events
954961
/// provide failure information for each path attempt in the payment, including retries.
@@ -1556,14 +1563,15 @@ impl Writeable for Event {
15561563
(13, payment_id, option),
15571564
});
15581565
},
1559-
&Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref amount_msat, ref fee_paid_msat } => {
1566+
&Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref amount_msat, ref fee_paid_msat, ref bolt12_invoice } => {
15601567
2u8.write(writer)?;
15611568
write_tlv_fields!(writer, {
15621569
(0, payment_preimage, required),
15631570
(1, payment_hash, required),
15641571
(3, payment_id, option),
15651572
(5, fee_paid_msat, option),
15661573
(7, amount_msat, option),
1574+
(9, bolt12_invoice, option),
15671575
});
15681576
},
15691577
&Event::PaymentPathFailed {
@@ -1898,12 +1906,14 @@ impl MaybeReadable for Event {
18981906
let mut payment_id = None;
18991907
let mut amount_msat = None;
19001908
let mut fee_paid_msat = None;
1909+
let mut bolt12_invoice = None;
19011910
read_tlv_fields!(reader, {
19021911
(0, payment_preimage, required),
19031912
(1, payment_hash, option),
19041913
(3, payment_id, option),
19051914
(5, fee_paid_msat, option),
19061915
(7, amount_msat, option),
1916+
(9, bolt12_invoice, option),
19071917
});
19081918
if payment_hash.is_none() {
19091919
payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()));
@@ -1914,6 +1924,7 @@ impl MaybeReadable for Event {
19141924
payment_hash: payment_hash.unwrap(),
19151925
amount_msat,
19161926
fee_paid_msat,
1927+
bolt12_invoice,
19171928
}))
19181929
};
19191930
f()

lightning/src/ln/functional_test_utils.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use crate::util::test_channel_signer::SignerOp;
3535
use crate::util::test_utils;
3636
use crate::util::test_utils::{TestChainMonitor, TestScorer, TestKeysInterface};
3737
use crate::util::ser::{ReadableArgs, Writeable};
38+
use crate::offers::invoice::Bolt12Invoice;
3839

3940
use bitcoin::{Weight, WPubkeyHash};
4041
use bitcoin::amount::Amount;
@@ -3116,10 +3117,11 @@ pub fn claim_payment_along_route(args: ClaimAlongRouteArgs) {
31163117
}
31173118
}
31183119

3119-
pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage) {
3120+
pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage) -> Option<Bolt12Invoice> {
31203121
claim_payment_along_route(
31213122
ClaimAlongRouteArgs::new(origin_node, &[expected_route], our_payment_preimage)
31223123
);
3124+
None
31233125
}
31243126

31253127
pub const TEST_FINAL_CLTV: u32 = 70;

lightning/src/ln/offers_tests.rs

+14-12
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ fn route_bolt12_payment<'a, 'b, 'c>(
168168
}
169169

170170
fn claim_bolt12_payment<'a, 'b, 'c>(
171-
node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], expected_payment_context: PaymentContext
171+
node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], expected_payment_context: PaymentContext, invoice: &Bolt12Invoice
172172
) {
173173
let recipient = &path[path.len() - 1];
174174
let payment_purpose = match get_event!(recipient, Event::PaymentClaimable) {
@@ -188,7 +188,9 @@ fn claim_bolt12_payment<'a, 'b, 'c>(
188188
},
189189
_ => panic!("Unexpected payment purpose: {:?}", payment_purpose),
190190
}
191-
claim_payment(node, path, payment_preimage);
191+
if let Some(inv) = claim_payment(node, path, payment_preimage) {
192+
assert_eq!(inv, invoice.to_owned());
193+
};
192194
}
193195

194196
fn extract_offer_nonce<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage) -> Nonce {
@@ -597,7 +599,7 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() {
597599
route_bolt12_payment(david, &[charlie, bob, alice], &invoice);
598600
expect_recent_payment!(david, RecentPaymentDetails::Pending, payment_id);
599601

600-
claim_bolt12_payment(david, &[charlie, bob, alice], payment_context);
602+
claim_bolt12_payment(david, &[charlie, bob, alice], payment_context, &invoice);
601603
expect_recent_payment!(david, RecentPaymentDetails::Fulfilled, payment_id);
602604
}
603605

@@ -680,7 +682,7 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() {
680682
route_bolt12_payment(david, &[charlie, bob, alice], &invoice);
681683
expect_recent_payment!(david, RecentPaymentDetails::Pending, payment_id);
682684

683-
claim_bolt12_payment(david, &[charlie, bob, alice], payment_context);
685+
claim_bolt12_payment(david, &[charlie, bob, alice], payment_context, &invoice);
684686
expect_recent_payment!(david, RecentPaymentDetails::Fulfilled, payment_id);
685687
}
686688

@@ -747,7 +749,7 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() {
747749
route_bolt12_payment(bob, &[alice], &invoice);
748750
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
749751

750-
claim_bolt12_payment(bob, &[alice], payment_context);
752+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
751753
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
752754
}
753755

@@ -803,7 +805,7 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() {
803805
route_bolt12_payment(bob, &[alice], &invoice);
804806
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
805807

806-
claim_bolt12_payment(bob, &[alice], payment_context);
808+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
807809
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
808810
}
809811

@@ -857,7 +859,7 @@ fn pays_for_offer_without_blinded_paths() {
857859
route_bolt12_payment(bob, &[alice], &invoice);
858860
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
859861

860-
claim_bolt12_payment(bob, &[alice], payment_context);
862+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
861863
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
862864
}
863865

@@ -900,7 +902,7 @@ fn pays_for_refund_without_blinded_paths() {
900902
route_bolt12_payment(bob, &[alice], &invoice);
901903
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
902904

903-
claim_bolt12_payment(bob, &[alice], payment_context);
905+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
904906
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
905907
}
906908

@@ -1138,7 +1140,7 @@ fn creates_and_pays_for_offer_with_retry() {
11381140
}
11391141
route_bolt12_payment(bob, &[alice], &invoice);
11401142
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
1141-
claim_bolt12_payment(bob, &[alice], payment_context);
1143+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
11421144
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
11431145
}
11441146

@@ -1209,7 +1211,7 @@ fn pays_bolt12_invoice_asynchronously() {
12091211
route_bolt12_payment(bob, &[alice], &invoice);
12101212
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
12111213

1212-
claim_bolt12_payment(bob, &[alice], payment_context);
1214+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
12131215
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
12141216

12151217
assert_eq!(
@@ -1289,7 +1291,7 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() {
12891291
route_bolt12_payment(bob, &[alice], &invoice);
12901292
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
12911293

1292-
claim_bolt12_payment(bob, &[alice], payment_context);
1294+
claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
12931295
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
12941296
}
12951297

@@ -2145,7 +2147,7 @@ fn fails_paying_invoice_more_than_once() {
21452147
assert!(david.node.get_and_clear_pending_msg_events().is_empty());
21462148

21472149
// Complete paying the first invoice
2148-
claim_bolt12_payment(david, &[charlie, bob, alice], payment_context);
2150+
claim_bolt12_payment(david, &[charlie, bob, alice], payment_context, &invoice1);
21492151
expect_recent_payment!(david, RecentPaymentDetails::Fulfilled, payment_id);
21502152
}
21512153

lightning/src/ln/outbound_payment.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2028,6 +2028,7 @@ impl OutboundPayments {
20282028
payment_hash,
20292029
amount_msat,
20302030
fee_paid_msat,
2031+
bolt12_invoice: payment.get().bolt12_invoice().cloned(),
20312032
}, Some(ev_completion_action.clone())));
20322033
payment.get_mut().mark_fulfilled();
20332034
}

0 commit comments

Comments
 (0)