Expose description from Invoice's offer/refund
authorJeffrey Czyz <jkczyz@gmail.com>
Thu, 20 Apr 2023 13:30:18 +0000 (08:30 -0500)
committerJeffrey Czyz <jkczyz@gmail.com>
Thu, 20 Apr 2023 13:41:07 +0000 (08:41 -0500)
This will allow clients like VLS to check the description for an invoice
as part of verification.

lightning/src/offers/invoice.rs
lightning/src/offers/offer.rs
lightning/src/offers/refund.rs

index b2717f7338f193cd17589ee7e3216c972d7463ad..6bf155a230324a48c29c5b5c5d0b9cb06ed04a97 100644 (file)
@@ -117,6 +117,7 @@ use crate::offers::refund::{IV_BYTES as REFUND_IV_BYTES, Refund, RefundContents}
 use crate::offers::signer;
 use crate::onion_message::BlindedPath;
 use crate::util::ser::{HighZeroBytesDroppedBigSize, Iterable, SeekReadable, WithoutLength, Writeable, Writer};
+use crate::util::string::PrintableString;
 
 use crate::prelude::*;
 
@@ -452,6 +453,12 @@ struct InvoiceFields {
 }
 
 impl Invoice {
+       /// A complete description of the purpose of the originating offer or refund. Intended to be
+       /// displayed to the user but with the caveat that it has not been verified in any way.
+       pub fn description(&self) -> PrintableString {
+               self.contents.description()
+       }
+
        /// Paths to the recipient originating from publicly reachable nodes, including information
        /// needed for routing payments across them.
        ///
@@ -607,6 +614,15 @@ impl InvoiceContents {
                }
        }
 
+       fn description(&self) -> PrintableString {
+               match self {
+                       InvoiceContents::ForOffer { invoice_request, .. } => {
+                               invoice_request.inner.offer.description()
+                       },
+                       InvoiceContents::ForRefund { refund, .. } => refund.description(),
+               }
+       }
+
        fn fields(&self) -> &InvoiceFields {
                match self {
                        InvoiceContents::ForOffer { fields, .. } => fields,
@@ -939,6 +955,7 @@ mod tests {
        use crate::offers::test_utils::*;
        use crate::onion_message::{BlindedHop, BlindedPath};
        use crate::util::ser::{BigSize, Iterable, Writeable};
+       use crate::util::string::PrintableString;
 
        trait ToBytes {
                fn to_bytes(&self) -> Vec<u8>;
@@ -975,6 +992,7 @@ mod tests {
                invoice.write(&mut buffer).unwrap();
 
                assert_eq!(invoice.bytes, buffer.as_slice());
+               assert_eq!(invoice.description(), PrintableString("foo"));
                assert_eq!(invoice.payment_paths(), payment_paths.as_slice());
                assert_eq!(invoice.created_at(), now);
                assert_eq!(invoice.relative_expiry(), DEFAULT_RELATIVE_EXPIRY);
@@ -1057,6 +1075,7 @@ mod tests {
                invoice.write(&mut buffer).unwrap();
 
                assert_eq!(invoice.bytes, buffer.as_slice());
+               assert_eq!(invoice.description(), PrintableString("foo"));
                assert_eq!(invoice.payment_paths(), payment_paths.as_slice());
                assert_eq!(invoice.created_at(), now);
                assert_eq!(invoice.relative_expiry(), DEFAULT_RELATIVE_EXPIRY);
index d2918e809429d8f5db858b52930e8e19634e869e..192317240f94df2e61ffbe7269f97cd3d4d22701 100644 (file)
@@ -384,7 +384,7 @@ impl Offer {
        /// A complete description of the purpose of the payment. Intended to be displayed to the user
        /// but with the caveat that it has not been verified in any way.
        pub fn description(&self) -> PrintableString {
-               PrintableString(&self.contents.description)
+               self.contents.description()
        }
 
        /// Features pertaining to the offer.
@@ -536,6 +536,10 @@ impl OfferContents {
                self.metadata.as_ref().and_then(|metadata| metadata.as_bytes())
        }
 
+       pub fn description(&self) -> PrintableString {
+               PrintableString(&self.description)
+       }
+
        #[cfg(feature = "std")]
        pub(super) fn is_expired(&self) -> bool {
                match self.absolute_expiry {
index f677a2a9cdb61fcdf5f5fe9f5389a6dba895512c..eac7a3754edf54444d3b87b6c3b31fd5ccf4f3dd 100644 (file)
@@ -310,7 +310,7 @@ impl Refund {
        /// A complete description of the purpose of the refund. Intended to be displayed to the user
        /// but with the caveat that it has not been verified in any way.
        pub fn description(&self) -> PrintableString {
-               PrintableString(&self.contents.description)
+               self.contents.description()
        }
 
        /// Duration since the Unix epoch when an invoice should no longer be sent.
@@ -489,6 +489,10 @@ impl AsRef<[u8]> for Refund {
 }
 
 impl RefundContents {
+       pub fn description(&self) -> PrintableString {
+               PrintableString(&self.description)
+       }
+
        #[cfg(feature = "std")]
        pub(super) fn is_expired(&self) -> bool {
                match self.absolute_expiry {