Skip to content

Commit 46ea200

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: #3344 Signed-off-by: Vincenzo Palazzo <[email protected]>
1 parent f80cd8d commit 46ea200

File tree

7 files changed

+130
-56
lines changed

7 files changed

+130
-56
lines changed

lightning/src/events/mod.rs

+33-2
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, Paym
2323
use crate::chain::transaction;
2424
use crate::ln::channelmanager::{InterceptId, PaymentId, RecipientOnionFields};
2525
use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS;
26+
use crate::offers::invoice::Bolt12Invoice;
27+
use crate::offers::static_invoice::StaticInvoice;
2628
use crate::types::features::ChannelTypeFeatures;
2729
use crate::ln::msgs;
2830
use crate::ln::types::ChannelId;
2931
use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret};
30-
use crate::offers::invoice::Bolt12Invoice;
3132
use crate::onion_message::messenger::Responder;
3233
use crate::routing::gossip::NetworkUpdate;
3334
use crate::routing::router::{BlindedTail, Path, RouteHop, RouteParameters};
@@ -949,6 +950,18 @@ pub enum Event {
949950
///
950951
/// [`Route::get_total_fees`]: crate::routing::router::Route::get_total_fees
951952
fee_paid_msat: Option<u64>,
953+
/// The BOLT 12 invoice that was paid. `None` if the payment was a non BOLT 12 payment.
954+
///
955+
/// The BOLT 12 invoice is useful for proof of payment because it contains the
956+
/// payment hash. A third party can verify that the payment was made by
957+
/// showing the invoice and confirming that the payment hash matches
958+
/// the hash of the payment preimage.
959+
///
960+
/// However, the [`PaidBolt12Invoice`] can also be of type [`StaticInvoice`], which
961+
/// is a special [`Bolt12Invoice`] where proof of payment is not possible.
962+
///
963+
/// [`StaticInvoice`]: crate::offers::static_invoice::StaticInvoice
964+
bolt12_invoice: Option<PaidBolt12Invoice>,
952965
},
953966
/// Indicates an outbound payment failed. Individual [`Event::PaymentPathFailed`] events
954967
/// provide failure information for each path attempt in the payment, including retries.
@@ -1556,14 +1569,15 @@ impl Writeable for Event {
15561569
(13, payment_id, option),
15571570
});
15581571
},
1559-
&Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref amount_msat, ref fee_paid_msat } => {
1572+
&Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref amount_msat, ref fee_paid_msat, ref bolt12_invoice } => {
15601573
2u8.write(writer)?;
15611574
write_tlv_fields!(writer, {
15621575
(0, payment_preimage, required),
15631576
(1, payment_hash, required),
15641577
(3, payment_id, option),
15651578
(5, fee_paid_msat, option),
15661579
(7, amount_msat, option),
1580+
(9, bolt12_invoice, option),
15671581
});
15681582
},
15691583
&Event::PaymentPathFailed {
@@ -1898,12 +1912,14 @@ impl MaybeReadable for Event {
18981912
let mut payment_id = None;
18991913
let mut amount_msat = None;
19001914
let mut fee_paid_msat = None;
1915+
let mut bolt12_invoice = None;
19011916
read_tlv_fields!(reader, {
19021917
(0, payment_preimage, required),
19031918
(1, payment_hash, option),
19041919
(3, payment_id, option),
19051920
(5, fee_paid_msat, option),
19061921
(7, amount_msat, option),
1922+
(9, bolt12_invoice, option),
19071923
});
19081924
if payment_hash.is_none() {
19091925
payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array()));
@@ -1914,6 +1930,7 @@ impl MaybeReadable for Event {
19141930
payment_hash: payment_hash.unwrap(),
19151931
amount_msat,
19161932
fee_paid_msat,
1933+
bolt12_invoice,
19171934
}))
19181935
};
19191936
f()
@@ -2438,3 +2455,17 @@ impl<T: EventHandler> EventHandler for Arc<T> {
24382455
self.deref().handle_event(event)
24392456
}
24402457
}
2458+
2459+
/// The BOLT 12 invoice that was paid, surfaced in [`Event::PaymentSent::bolt12_invoice`].
2460+
#[derive(Clone, Debug, PartialEq, Eq)]
2461+
pub enum PaidBolt12Invoice {
2462+
///
2463+
Bolt12Invoice(Bolt12Invoice),
2464+
///
2465+
StaticInvoice(StaticInvoice),
2466+
}
2467+
2468+
impl_writeable_tlv_based_enum!(PaidBolt12Invoice,
2469+
{0, Bolt12Invoice} => (),
2470+
{2, StaticInvoice} => (),
2471+
);

lightning/src/ln/async_payments_tests.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::blinded_path::message::{MessageContext, OffersContext};
1111
use crate::blinded_path::payment::PaymentContext;
1212
use crate::blinded_path::payment::{AsyncBolt12OfferContext, BlindedPaymentTlvs};
1313
use crate::chain::channelmonitor::{HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
14-
use crate::events::{Event, HTLCDestination, PaymentFailureReason};
14+
use crate::events::{Event, HTLCDestination, PaidInvoice, PaymentFailureReason};
1515
use crate::ln::blinded_payment_tests::{fail_blinded_htlc_backwards, get_blinded_route_parameters};
1616
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
1717
use crate::ln::functional_test_utils::*;
@@ -420,7 +420,7 @@ fn async_receive_flow_success() {
420420
.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(0), params)
421421
.unwrap();
422422
let release_held_htlc_om =
423-
pass_async_payments_oms(static_invoice, &nodes[0], &nodes[1], &nodes[2]).1;
423+
pass_async_payments_oms(static_invoice.clone(), &nodes[0], &nodes[1], &nodes[2]).1;
424424
nodes[0]
425425
.onion_messenger
426426
.handle_onion_message(nodes[2].node.get_our_node_id(), &release_held_htlc_om);
@@ -441,7 +441,10 @@ fn async_receive_flow_success() {
441441
let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
442442
.with_payment_preimage(keysend_preimage);
443443
do_pass_along_path(args);
444-
claim_payment_along_route(ClaimAlongRouteArgs::new(&nodes[0], route, keysend_preimage));
444+
let res =
445+
claim_payment_along_route(ClaimAlongRouteArgs::new(&nodes[0], route, keysend_preimage));
446+
assert!(res.is_some());
447+
assert_eq!(res, Some(PaidInvoice::StaticInvoice(static_invoice)));
445448
}
446449

447450
#[cfg_attr(feature = "std", ignore)]

lightning/src/ln/functional_test_utils.rs

+16-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, PaidBolt12Invoice, 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<PaidBolt12Invoice> {
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,10 @@ 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+
let invoice;
23092311
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 } => {
2312+
Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref amount_msat, ref fee_paid_msat, ref bolt12_invoice } => {
23112313
assert_eq!(expected_payment_preimage, *payment_preimage);
23122314
assert_eq!(expected_payment_hash, *payment_hash);
23132315
assert!(amount_msat.is_some());
@@ -2316,6 +2318,7 @@ pub fn expect_payment_sent<CM: AChannelManager, H: NodeHolder<CM=CM>>(node: &H,
23162318
} else {
23172319
assert!(fee_paid_msat.is_some());
23182320
}
2321+
invoice = bolt12_invoice.clone();
23192322
payment_id.unwrap()
23202323
},
23212324
_ => panic!("Unexpected event"),
@@ -2331,19 +2334,20 @@ pub fn expect_payment_sent<CM: AChannelManager, H: NodeHolder<CM=CM>>(node: &H,
23312334
}
23322335
}
23332336
}
2337+
invoice
23342338
}
23352339

23362340
#[macro_export]
23372341
macro_rules! expect_payment_sent {
23382342
($node: expr, $expected_payment_preimage: expr) => {
2339-
$crate::expect_payment_sent!($node, $expected_payment_preimage, None::<u64>, true);
2343+
$crate::expect_payment_sent!($node, $expected_payment_preimage, None::<u64>, true)
23402344
};
23412345
($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);
2346+
$crate::expect_payment_sent!($node, $expected_payment_preimage, $expected_fee_msat_opt, true)
23432347
};
23442348
($node: expr, $expected_payment_preimage: expr, $expected_fee_msat_opt: expr, $expect_paths: expr) => {
23452349
$crate::ln::functional_test_utils::expect_payment_sent(&$node, $expected_payment_preimage,
2346-
$expected_fee_msat_opt.map(|o| Some(o)), $expect_paths, true);
2350+
$expected_fee_msat_opt.map(|o| Some(o)), $expect_paths, true)
23472351
}
23482352
}
23492353

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

31073111
expected_total_fee_msat
31083112
}
3109-
pub fn claim_payment_along_route(args: ClaimAlongRouteArgs) {
3113+
pub fn claim_payment_along_route(args: ClaimAlongRouteArgs) -> Option<PaidBolt12Invoice> {
31103114
let origin_node = args.origin_node;
31113115
let payment_preimage = args.payment_preimage;
31123116
let skip_last = args.skip_last;
31133117
let expected_total_fee_msat = do_claim_payment_along_route(args);
31143118
if !skip_last {
3115-
expect_payment_sent!(origin_node, payment_preimage, Some(expected_total_fee_msat));
3119+
expect_payment_sent!(origin_node, payment_preimage, Some(expected_total_fee_msat))
3120+
} else {
3121+
None
31163122
}
31173123
}
31183124

3119-
pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage) {
3125+
pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage) -> Option<PaidBolt12Invoice> {
31203126
claim_payment_along_route(
31213127
ClaimAlongRouteArgs::new(origin_node, &[expected_route], our_payment_preimage)
3122-
);
3128+
)
31233129
}
31243130

31253131
pub const TEST_FINAL_CLTV: u32 = 70;

lightning/src/ln/offers_tests.rs

+17-13
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use crate::blinded_path::IntroductionNode;
4747
use crate::blinded_path::message::BlindedMessagePath;
4848
use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext};
4949
use crate::blinded_path::message::OffersContext;
50-
use crate::events::{ClosureReason, Event, HTLCDestination, PaymentFailureReason, PaymentPurpose};
50+
use crate::events::{ClosureReason, Event, HTLCDestination, PaidBolt12Invoice, PaymentFailureReason, PaymentPurpose};
5151
use crate::ln::channelmanager::{Bolt12PaymentError, MAX_SHORT_LIVED_RELATIVE_EXPIRY, PaymentId, RecentPaymentDetails, RecipientOnionFields, Retry, self};
5252
use crate::types::features::Bolt12InvoiceFeatures;
5353
use crate::ln::functional_test_utils::*;
@@ -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, PaidBolt12Invoice::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)