Skip to content

Commit a88e206

Browse files
storage: store the bolt12invoice invoice
This commit enhances the BOLT12 payment storage capabilities by adding support for storing the actual BOLT12 invoice along with payment details. We modify the following components: - Added `bolt12_invoice` field to `PaymentKind::Bolt12Offer` and `PaymentKind::Bolt12Refund` variants in the payment store - Updated event handling in `event.rs` to capture and store the BOLT12 invoice when payments are processed - Modified BOLT12 payment creation logic to initialize the new field - Enhanced payment update mechanism to handle BOLT12 invoice updates - Added comprehensive test coverage for the new invoice storage feature This improvement allows for proof of payment and to access the BOLT12 invoice details. Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
1 parent a12ceaf commit a88e206

File tree

4 files changed

+46
-8
lines changed

4 files changed

+46
-8
lines changed

src/event.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,7 @@ where
745745
offer_id,
746746
payer_note,
747747
quantity,
748+
bolt12_invoice: None,
748749
};
749750

750751
let payment = PaymentDetails::new(
@@ -949,6 +950,7 @@ where
949950
payment_preimage,
950951
payment_hash,
951952
fee_paid_msat,
953+
bolt12_invoice,
952954
..
953955
} => {
954956
let payment_id = if let Some(id) = payment_id {
@@ -963,6 +965,7 @@ where
963965
preimage: Some(Some(payment_preimage)),
964966
fee_paid_msat: Some(fee_paid_msat),
965967
status: Some(PaymentStatus::Succeeded),
968+
bolt12_invoice: Some(bolt12_invoice),
966969
..PaymentDetailsUpdate::new(payment_id)
967970
};
968971

src/payment/bolt12.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::logger::{log_error, log_info, LdkLogger, Logger};
1515
use crate::payment::store::{PaymentDetails, PaymentDirection, PaymentKind, PaymentStatus};
1616
use crate::types::{ChannelManager, PaymentStore};
1717

18+
use lightning::events::PaidBolt12Invoice;
1819
use lightning::ln::channelmanager::{PaymentId, Retry};
1920
use lightning::offers::invoice::Bolt12Invoice;
2021
use lightning::offers::offer::{Amount, Offer, Quantity};
@@ -107,6 +108,7 @@ impl Bolt12Payment {
107108
offer_id: offer.id(),
108109
payer_note: payer_note.map(UntrustedString),
109110
quantity,
111+
bolt12_invoice: None,
110112
};
111113
let payment = PaymentDetails::new(
112114
payment_id,
@@ -132,6 +134,7 @@ impl Bolt12Payment {
132134
offer_id: offer.id(),
133135
payer_note: payer_note.map(UntrustedString),
134136
quantity,
137+
bolt12_invoice: None,
135138
};
136139
let payment = PaymentDetails::new(
137140
payment_id,
@@ -213,6 +216,7 @@ impl Bolt12Payment {
213216
offer_id: offer.id(),
214217
payer_note: payer_note.map(UntrustedString),
215218
quantity,
219+
bolt12_invoice: None,
216220
};
217221
let payment = PaymentDetails::new(
218222
payment_id,
@@ -238,6 +242,7 @@ impl Bolt12Payment {
238242
offer_id: offer.id(),
239243
payer_note: payer_note.map(UntrustedString),
240244
quantity,
245+
bolt12_invoice: None,
241246
};
242247
let payment = PaymentDetails::new(
243248
payment_id,
@@ -335,6 +340,7 @@ impl Bolt12Payment {
335340
secret: None,
336341
payer_note: refund.payer_note().map(|note| UntrustedString(note.0.to_string())),
337342
quantity: refund.quantity(),
343+
bolt12_invoice: Some(PaidBolt12Invoice::Bolt12Invoice(invoice.clone())),
338344
};
339345

340346
let payment = PaymentDetails::new(
@@ -401,6 +407,7 @@ impl Bolt12Payment {
401407
secret: None,
402408
payer_note: payer_note.map(|note| UntrustedString(note)),
403409
quantity,
410+
bolt12_invoice: None,
404411
};
405412
let payment = PaymentDetails::new(
406413
payment_id,

src/payment/store.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// http://opensource.org/licenses/MIT>, at your option. You may not use this file except in
66
// accordance with one or both of these licenses.
77

8+
use lightning::events::PaidBolt12Invoice;
89
use lightning::ln::channelmanager::PaymentId;
910
use lightning::ln::msgs::DecodeError;
1011
use lightning::offers::offer::OfferId;
@@ -293,6 +294,18 @@ impl StorableObject for PaymentDetails {
293294
}
294295
}
295296

297+
if let Some(ref bolt12_invoice_opt) = update.bolt12_invoice {
298+
match self.kind {
299+
PaymentKind::Bolt12Offer { ref mut bolt12_invoice, .. } => {
300+
update_if_necessary!(*bolt12_invoice, bolt12_invoice_opt.clone());
301+
},
302+
PaymentKind::Bolt12Refund { ref mut bolt12_invoice, .. } => {
303+
update_if_necessary!(*bolt12_invoice, bolt12_invoice_opt.clone());
304+
},
305+
_ => {},
306+
}
307+
}
308+
296309
if updated {
297310
self.latest_update_timestamp = SystemTime::now()
298311
.duration_since(UNIX_EPOCH)
@@ -417,6 +430,8 @@ pub enum PaymentKind {
417430
///
418431
/// This will always be `None` for payments serialized with version `v0.3.0`.
419432
quantity: Option<u64>,
433+
/// TODO: need to be documented
434+
bolt12_invoice: Option<PaidBolt12Invoice>,
420435
},
421436
/// A [BOLT 12] 'refund' payment, i.e., a payment for a [`Refund`].
422437
///
@@ -437,6 +452,8 @@ pub enum PaymentKind {
437452
///
438453
/// This will always be `None` for payments serialized with version `v0.3.0`.
439454
quantity: Option<u64>,
455+
/// TODO: need to be documented
456+
bolt12_invoice: Option<PaidBolt12Invoice>,
440457
},
441458
/// A spontaneous ("keysend") payment.
442459
Spontaneous {
@@ -471,6 +488,7 @@ impl_writeable_tlv_based_enum!(PaymentKind,
471488
(3, quantity, option),
472489
(4, secret, option),
473490
(6, offer_id, required),
491+
(8, bolt12_invoice, option),
474492
},
475493
(8, Spontaneous) => {
476494
(0, hash, required),
@@ -482,6 +500,7 @@ impl_writeable_tlv_based_enum!(PaymentKind,
482500
(2, preimage, option),
483501
(3, quantity, option),
484502
(4, secret, option),
503+
(6, bolt12_invoice, option),
485504
}
486505
);
487506

@@ -542,6 +561,7 @@ pub(crate) struct PaymentDetailsUpdate {
542561
pub direction: Option<PaymentDirection>,
543562
pub status: Option<PaymentStatus>,
544563
pub confirmation_status: Option<ConfirmationStatus>,
564+
pub bolt12_invoice: Option<Option<PaidBolt12Invoice>>,
545565
}
546566

547567
impl PaymentDetailsUpdate {
@@ -557,19 +577,20 @@ impl PaymentDetailsUpdate {
557577
direction: None,
558578
status: None,
559579
confirmation_status: None,
580+
bolt12_invoice: None,
560581
}
561582
}
562583
}
563584

564585
impl From<&PaymentDetails> for PaymentDetailsUpdate {
565586
fn from(value: &PaymentDetails) -> Self {
566-
let (hash, preimage, secret) = match value.kind {
567-
PaymentKind::Bolt11 { hash, preimage, secret, .. } => (Some(hash), preimage, secret),
568-
PaymentKind::Bolt11Jit { hash, preimage, secret, .. } => (Some(hash), preimage, secret),
569-
PaymentKind::Bolt12Offer { hash, preimage, secret, .. } => (hash, preimage, secret),
570-
PaymentKind::Bolt12Refund { hash, preimage, secret, .. } => (hash, preimage, secret),
571-
PaymentKind::Spontaneous { hash, preimage, .. } => (Some(hash), preimage, None),
572-
_ => (None, None, None),
587+
let (hash, preimage, secret, bolt12_invoice) = match value.kind {
588+
PaymentKind::Bolt11 { hash, preimage, secret, .. } => (Some(hash), preimage, secret, None),
589+
PaymentKind::Bolt11Jit { hash, preimage, secret, .. } => (Some(hash), preimage, secret, None),
590+
PaymentKind::Bolt12Offer { hash, preimage, secret, ref bolt12_invoice, .. } => (hash, preimage, secret, Some(bolt12_invoice)),
591+
PaymentKind::Bolt12Refund { hash, preimage, secret, ref bolt12_invoice, .. } => (hash, preimage, secret, Some(bolt12_invoice)),
592+
PaymentKind::Spontaneous { hash, preimage, .. } => (Some(hash), preimage, None, None),
593+
_ => (None, None, None, None),
573594
};
574595

575596
let confirmation_status = match value.kind {
@@ -595,6 +616,7 @@ impl From<&PaymentDetails> for PaymentDetailsUpdate {
595616
direction: Some(value.direction),
596617
status: Some(value.status),
597618
confirmation_status,
619+
bolt12_invoice: bolt12_invoice.cloned(),
598620
}
599621
}
600622
}

tests/integration_tests_rust.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,12 +817,14 @@ fn simple_bolt12_send_receive() {
817817
offer_id,
818818
quantity: ref qty,
819819
payer_note: ref note,
820+
bolt12_invoice: ref invoice,
820821
} => {
821822
assert!(hash.is_some());
822823
assert!(preimage.is_some());
823824
assert_eq!(offer_id, offer.id());
824825
assert_eq!(&expected_quantity, qty);
825826
assert_eq!(expected_payer_note.unwrap(), note.clone().unwrap().0);
827+
assert!(invoice.is_some());
826828
//TODO: We should eventually set and assert the secret sender-side, too, but the BOLT12
827829
//API currently doesn't allow to do that.
828830
},
@@ -883,12 +885,14 @@ fn simple_bolt12_send_receive() {
883885
offer_id,
884886
quantity: ref qty,
885887
payer_note: ref note,
888+
bolt12_invoice: ref invoice,
886889
} => {
887890
assert!(hash.is_some());
888891
assert!(preimage.is_some());
889892
assert_eq!(offer_id, offer.id());
890893
assert_eq!(&expected_quantity, qty);
891894
assert_eq!(expected_payer_note.unwrap(), note.clone().unwrap().0);
895+
assert!(invoice.is_some());
892896
//TODO: We should eventually set and assert the secret sender-side, too, but the BOLT12
893897
//API currently doesn't allow to do that.
894898
hash.unwrap()
@@ -950,11 +954,13 @@ fn simple_bolt12_send_receive() {
950954
secret: _,
951955
quantity: ref qty,
952956
payer_note: ref note,
957+
bolt12_invoice: ref invoice,
953958
} => {
954959
assert!(hash.is_some());
955960
assert!(preimage.is_some());
956961
assert_eq!(&expected_quantity, qty);
957-
assert_eq!(expected_payer_note.unwrap(), note.clone().unwrap().0)
962+
assert_eq!(expected_payer_note.unwrap(), note.clone().unwrap().0);
963+
assert!(invoice.is_some());
958964
//TODO: We should eventually set and assert the secret sender-side, too, but the BOLT12
959965
//API currently doesn't allow to do that.
960966
},

0 commit comments

Comments
 (0)