X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Foffers%2Finvoice.rs;h=4d1398644ce0d24483205b0ac04e428ba3d52482;hb=38a2186cb6091f4b041bf18c3fd0e3f714db93b7;hp=0cc6c407c1dc0e39a3082adc11251e8881ac11f8;hpb=c8a847ae11f50765c59c79503c127235131ee479;p=rust-lightning diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index 0cc6c407..4d139864 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -29,7 +29,7 @@ //! //! # use lightning::ln::PaymentHash; //! # use lightning::offers::invoice::BlindedPayInfo; -//! # use lightning::onion_message::BlindedPath; +//! # use lightning::blinded_path::BlindedPath; //! # //! # fn create_payment_paths() -> Vec<(BlindedPath, BlindedPayInfo)> { unimplemented!() } //! # fn create_payment_hash() -> PaymentHash { unimplemented!() } @@ -104,6 +104,7 @@ use bitcoin::util::schnorr::TweakedPublicKey; use core::convert::{Infallible, TryFrom}; use core::time::Duration; use crate::io; +use crate::blinded_path::BlindedPath; use crate::ln::PaymentHash; use crate::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures}; use crate::ln::inbound_payment::ExpandedKey; @@ -115,8 +116,8 @@ use crate::offers::parse::{ParseError, ParsedMessage, SemanticError}; use crate::offers::payer::{PAYER_METADATA_TYPE, PayerTlvStream, PayerTlvStreamRef}; 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::*; @@ -133,6 +134,8 @@ pub(super) const SIGNATURE_TAG: &'static str = concat!("lightning", "invoice", " /// /// See [module-level documentation] for usage. /// +/// This is not exported to bindings users as builder patterns don't map outside of move semantics. +/// /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest /// [`Refund`]: crate::offers::refund::Refund /// [module-level documentation]: self @@ -144,12 +147,18 @@ pub struct InvoiceBuilder<'a, S: SigningPubkeyStrategy> { } /// Indicates how [`Invoice::signing_pubkey`] was set. +/// +/// This is not exported to bindings users as builder patterns don't map outside of move semantics. pub trait SigningPubkeyStrategy {} /// [`Invoice::signing_pubkey`] was explicitly set. +/// +/// This is not exported to bindings users as builder patterns don't map outside of move semantics. pub struct ExplicitSigningPubkey {} /// [`Invoice::signing_pubkey`] was derived. +/// +/// This is not exported to bindings users as builder patterns don't map outside of move semantics. pub struct DerivedSigningPubkey {} impl SigningPubkeyStrategy for ExplicitSigningPubkey {} @@ -161,13 +170,12 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> { created_at: Duration, payment_hash: PaymentHash ) -> Result { let amount_msats = Self::check_amount_msats(invoice_request)?; + let signing_pubkey = invoice_request.contents.inner.offer.signing_pubkey(); let contents = InvoiceContents::ForOffer { invoice_request: invoice_request.contents.clone(), - fields: InvoiceFields { - payment_paths, created_at, relative_expiry: None, payment_hash, amount_msats, - fallbacks: None, features: Bolt12InvoiceFeatures::empty(), - signing_pubkey: invoice_request.contents.inner.offer.signing_pubkey(), - }, + fields: Self::fields( + payment_paths, created_at, payment_hash, amount_msats, signing_pubkey + ), }; Self::new(&invoice_request.bytes, contents, None) @@ -177,13 +185,12 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> { refund: &'a Refund, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, created_at: Duration, payment_hash: PaymentHash, signing_pubkey: PublicKey ) -> Result { + let amount_msats = refund.amount_msats(); let contents = InvoiceContents::ForRefund { refund: refund.contents.clone(), - fields: InvoiceFields { - payment_paths, created_at, relative_expiry: None, payment_hash, - amount_msats: refund.amount_msats(), fallbacks: None, - features: Bolt12InvoiceFeatures::empty(), signing_pubkey, - }, + fields: Self::fields( + payment_paths, created_at, payment_hash, amount_msats, signing_pubkey + ), }; Self::new(&refund.bytes, contents, None) @@ -196,13 +203,12 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> { created_at: Duration, payment_hash: PaymentHash, keys: KeyPair ) -> Result { let amount_msats = Self::check_amount_msats(invoice_request)?; + let signing_pubkey = invoice_request.contents.inner.offer.signing_pubkey(); let contents = InvoiceContents::ForOffer { invoice_request: invoice_request.contents.clone(), - fields: InvoiceFields { - payment_paths, created_at, relative_expiry: None, payment_hash, amount_msats, - fallbacks: None, features: Bolt12InvoiceFeatures::empty(), - signing_pubkey: invoice_request.contents.inner.offer.signing_pubkey(), - }, + fields: Self::fields( + payment_paths, created_at, payment_hash, amount_msats, signing_pubkey + ), }; Self::new(&invoice_request.bytes, contents, Some(keys)) @@ -212,13 +218,13 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> { refund: &'a Refund, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, created_at: Duration, payment_hash: PaymentHash, keys: KeyPair, ) -> Result { + let amount_msats = refund.amount_msats(); + let signing_pubkey = keys.public_key(); let contents = InvoiceContents::ForRefund { refund: refund.contents.clone(), - fields: InvoiceFields { - payment_paths, created_at, relative_expiry: None, payment_hash, - amount_msats: refund.amount_msats(), fallbacks: None, - features: Bolt12InvoiceFeatures::empty(), signing_pubkey: keys.public_key(), - }, + fields: Self::fields( + payment_paths, created_at, payment_hash, amount_msats, signing_pubkey + ), }; Self::new(&refund.bytes, contents, Some(keys)) @@ -240,6 +246,16 @@ impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> { } } + fn fields( + payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, created_at: Duration, + payment_hash: PaymentHash, amount_msats: u64, signing_pubkey: PublicKey + ) -> InvoiceFields { + InvoiceFields { + payment_paths, created_at, relative_expiry: None, payment_hash, amount_msats, + fallbacks: None, features: Bolt12InvoiceFeatures::empty(), signing_pubkey, + } + } + fn new( invreq_bytes: &'a Vec, contents: InvoiceContents, keys: Option ) -> Result { @@ -361,6 +377,8 @@ impl<'a> UnsignedInvoice<'a> { } /// Signs the invoice using the given function. + /// + /// This is not exported to bindings users as functions aren't currently mapped. pub fn sign(self, sign: F) -> Result> where F: FnOnce(&Message) -> Result @@ -397,6 +415,8 @@ impl<'a> UnsignedInvoice<'a> { /// An invoice may be sent in response to an [`InvoiceRequest`] in the case of an offer or sent /// directly after scanning a refund. It includes all the information needed to pay a recipient. /// +/// This is not exported to bindings users as its name conflicts with the BOLT 11 Invoice type. +/// /// [`Offer`]: crate::offers::offer::Offer /// [`Refund`]: crate::offers::refund::Refund /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest @@ -445,6 +465,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. /// @@ -600,6 +626,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, @@ -725,7 +760,7 @@ type BlindedPayInfoIter<'a> = core::iter::Map< >; /// Information needed to route a payment across a [`BlindedPath`]. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Hash, Eq, PartialEq)] pub struct BlindedPayInfo { /// Base fee charged (in millisatoshi) for the entire blinded path. pub fee_base_msat: u32, @@ -919,7 +954,8 @@ mod tests { use bitcoin::util::schnorr::TweakedPublicKey; use core::convert::TryFrom; use core::time::Duration; - use crate::chain::keysinterface::KeyMaterial; + use crate::blinded_path::{BlindedHop, BlindedPath}; + use crate::sign::KeyMaterial; use crate::ln::features::Bolt12InvoiceFeatures; use crate::ln::inbound_payment::ExpandedKey; use crate::ln::msgs::DecodeError; @@ -930,8 +966,8 @@ mod tests { use crate::offers::payer::PayerTlvStreamRef; use crate::offers::refund::RefundBuilder; 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; @@ -968,6 +1004,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); @@ -1050,6 +1087,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);