Merge pull request #2411 from valentinewallace/2023-07-blinded-onion-keys
[rust-lightning] / lightning / src / offers / offer.rs
index 9c8489778b08eaee1e444fe3f2584345c5224582..d801be9d26fb969c0b89af9b84a5e7408726efea 100644 (file)
@@ -24,7 +24,7 @@
 //!
 //! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
 //! use lightning::offers::offer::{Offer, OfferBuilder, Quantity};
-//! use lightning::offers::parse::ParseError;
+//! use lightning::offers::parse::Bolt12ParseError;
 //! use lightning::util::ser::{Readable, Writeable};
 //!
 //! # use lightning::blinded_path::BlindedPath;
@@ -35,7 +35,7 @@
 //! # fn create_another_blinded_path() -> BlindedPath { unimplemented!() }
 //! #
 //! # #[cfg(feature = "std")]
-//! # fn build() -> Result<(), ParseError> {
+//! # fn build() -> Result<(), Bolt12ParseError> {
 //! let secp_ctx = Secp256k1::new();
 //! let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
 //! let pubkey = PublicKey::from(keys);
@@ -82,7 +82,7 @@ use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce};
 use crate::ln::msgs::MAX_VALUE_MSAT;
 use crate::offers::invoice_request::{DerivedPayerId, ExplicitPayerId, InvoiceRequestBuilder};
 use crate::offers::merkle::TlvStream;
-use crate::offers::parse::{Bech32Encode, ParseError, ParsedMessage, SemanticError};
+use crate::offers::parse::{Bech32Encode, Bolt12ParseError, Bolt12SemanticError, ParsedMessage};
 use crate::offers::signer::{Metadata, MetadataMaterial, self};
 use crate::util::ser::{HighZeroBytesDroppedBigSize, WithoutLength, Writeable, Writer};
 use crate::util::string::PrintableString;
@@ -146,7 +146,7 @@ impl<'a> OfferBuilder<'a, ExplicitMetadata, secp256k1::SignOnly> {
        /// Sets the [`Offer::metadata`] to the given bytes.
        ///
        /// Successive calls to this method will override the previous setting.
-       pub fn metadata(mut self, metadata: Vec<u8>) -> Result<Self, SemanticError> {
+       pub fn metadata(mut self, metadata: Vec<u8>) -> Result<Self, Bolt12SemanticError> {
                self.offer.metadata = Some(Metadata::Bytes(metadata));
                Ok(self)
        }
@@ -252,14 +252,14 @@ impl<'a, M: MetadataStrategy, T: secp256k1::Signing> OfferBuilder<'a, M, T> {
        }
 
        /// Builds an [`Offer`] from the builder's settings.
-       pub fn build(mut self) -> Result<Offer, SemanticError> {
+       pub fn build(mut self) -> Result<Offer, Bolt12SemanticError> {
                match self.offer.amount {
                        Some(Amount::Bitcoin { amount_msats }) => {
                                if amount_msats > MAX_VALUE_MSAT {
-                                       return Err(SemanticError::InvalidAmount);
+                                       return Err(Bolt12SemanticError::InvalidAmount);
                                }
                        },
-                       Some(Amount::Currency { .. }) => return Err(SemanticError::UnsupportedCurrency),
+                       Some(Amount::Currency { .. }) => return Err(Bolt12SemanticError::UnsupportedCurrency),
                        None => {},
                }
 
@@ -319,8 +319,8 @@ impl<'a, M: MetadataStrategy, T: secp256k1::Signing> OfferBuilder<'a, M, T> {
 /// An `Offer` is a potentially long-lived proposal for payment of a good or service.
 ///
 /// An offer is a precursor to an [`InvoiceRequest`]. A merchant publishes an offer from which a
-/// customer may request an [`Invoice`] for a specific quantity and using an amount sufficient to
-/// cover that quantity (i.e., at least `quantity * amount`). See [`Offer::amount`].
+/// customer may request an [`Bolt12Invoice`] for a specific quantity and using an amount sufficient
+/// to cover that quantity (i.e., at least `quantity * amount`). See [`Offer::amount`].
 ///
 /// Offers may be denominated in currency other than bitcoin but are ultimately paid using the
 /// latter.
@@ -328,7 +328,7 @@ impl<'a, M: MetadataStrategy, T: secp256k1::Signing> OfferBuilder<'a, M, T> {
 /// Through the use of [`BlindedPath`]s, offers provide recipient privacy.
 ///
 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
-/// [`Invoice`]: crate::offers::invoice::Invoice
+/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
 #[derive(Clone, Debug)]
 #[cfg_attr(test, derive(PartialEq))]
 pub struct Offer {
@@ -338,10 +338,11 @@ pub struct Offer {
        pub(super) contents: OfferContents,
 }
 
-/// The contents of an [`Offer`], which may be shared with an [`InvoiceRequest`] or an [`Invoice`].
+/// The contents of an [`Offer`], which may be shared with an [`InvoiceRequest`] or a
+/// [`Bolt12Invoice`].
 ///
 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
-/// [`Invoice`]: crate::offers::invoice::Invoice
+/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
 #[derive(Clone, Debug)]
 #[cfg_attr(test, derive(PartialEq))]
 pub(super) struct OfferContents {
@@ -451,8 +452,8 @@ impl Offer {
        /// - derives the [`InvoiceRequest::payer_id`] such that a different key can be used for each
        ///   request, and
        /// - sets the [`InvoiceRequest::metadata`] when [`InvoiceRequestBuilder::build`] is called such
-       ///   that it can be used by [`Invoice::verify`] to determine if the invoice was requested using
-       ///   a base [`ExpandedKey`] from which the payer id was derived.
+       ///   that it can be used by [`Bolt12Invoice::verify`] to determine if the invoice was requested
+       ///   using a base [`ExpandedKey`] from which the payer id was derived.
        ///
        /// Useful to protect the sender's privacy.
        ///
@@ -460,16 +461,16 @@ impl Offer {
        ///
        /// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id
        /// [`InvoiceRequest::metadata`]: crate::offers::invoice_request::InvoiceRequest::metadata
-       /// [`Invoice::verify`]: crate::offers::invoice::Invoice::verify
+       /// [`Bolt12Invoice::verify`]: crate::offers::invoice::Bolt12Invoice::verify
        /// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey
        pub fn request_invoice_deriving_payer_id<'a, 'b, ES: Deref, T: secp256k1::Signing>(
                &'a self, expanded_key: &ExpandedKey, entropy_source: ES, secp_ctx: &'b Secp256k1<T>
-       ) -> Result<InvoiceRequestBuilder<'a, 'b, DerivedPayerId, T>, SemanticError>
+       ) -> Result<InvoiceRequestBuilder<'a, 'b, DerivedPayerId, T>, Bolt12SemanticError>
        where
                ES::Target: EntropySource,
        {
                if self.features().requires_unknown_bits() {
-                       return Err(SemanticError::UnknownRequiredFeatures);
+                       return Err(Bolt12SemanticError::UnknownRequiredFeatures);
                }
 
                Ok(InvoiceRequestBuilder::deriving_payer_id(self, expanded_key, entropy_source, secp_ctx))
@@ -485,19 +486,19 @@ impl Offer {
        /// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id
        pub fn request_invoice_deriving_metadata<ES: Deref>(
                &self, payer_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES
-       ) -> Result<InvoiceRequestBuilder<ExplicitPayerId, secp256k1::SignOnly>, SemanticError>
+       ) -> Result<InvoiceRequestBuilder<ExplicitPayerId, secp256k1::SignOnly>, Bolt12SemanticError>
        where
                ES::Target: EntropySource,
        {
                if self.features().requires_unknown_bits() {
-                       return Err(SemanticError::UnknownRequiredFeatures);
+                       return Err(Bolt12SemanticError::UnknownRequiredFeatures);
                }
 
                Ok(InvoiceRequestBuilder::deriving_metadata(self, payer_id, expanded_key, entropy_source))
        }
 
        /// Creates an [`InvoiceRequestBuilder`] for the offer with the given `metadata` and `payer_id`,
-       /// which will be reflected in the `Invoice` response.
+       /// which will be reflected in the `Bolt12Invoice` response.
        ///
        /// The `metadata` is useful for including information about the derivation of `payer_id` such
        /// that invoice response handling can be stateless. Also serves as payer-provided entropy while
@@ -513,9 +514,9 @@ impl Offer {
        /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
        pub fn request_invoice(
                &self, metadata: Vec<u8>, payer_id: PublicKey
-       ) -> Result<InvoiceRequestBuilder<ExplicitPayerId, secp256k1::SignOnly>, SemanticError> {
+       ) -> Result<InvoiceRequestBuilder<ExplicitPayerId, secp256k1::SignOnly>, Bolt12SemanticError> {
                if self.features().requires_unknown_bits() {
-                       return Err(SemanticError::UnknownRequiredFeatures);
+                       return Err(Bolt12SemanticError::UnknownRequiredFeatures);
                }
 
                Ok(InvoiceRequestBuilder::new(self, metadata, payer_id))
@@ -571,24 +572,24 @@ impl OfferContents {
 
        pub(super) fn check_amount_msats_for_quantity(
                &self, amount_msats: Option<u64>, quantity: Option<u64>
-       ) -> Result<(), SemanticError> {
+       ) -> Result<(), Bolt12SemanticError> {
                let offer_amount_msats = match self.amount {
                        None => 0,
                        Some(Amount::Bitcoin { amount_msats }) => amount_msats,
-                       Some(Amount::Currency { .. }) => return Err(SemanticError::UnsupportedCurrency),
+                       Some(Amount::Currency { .. }) => return Err(Bolt12SemanticError::UnsupportedCurrency),
                };
 
                if !self.expects_quantity() || quantity.is_some() {
                        let expected_amount_msats = offer_amount_msats.checked_mul(quantity.unwrap_or(1))
-                               .ok_or(SemanticError::InvalidAmount)?;
+                               .ok_or(Bolt12SemanticError::InvalidAmount)?;
                        let amount_msats = amount_msats.unwrap_or(expected_amount_msats);
 
                        if amount_msats < expected_amount_msats {
-                               return Err(SemanticError::InsufficientAmount);
+                               return Err(Bolt12SemanticError::InsufficientAmount);
                        }
 
                        if amount_msats > MAX_VALUE_MSAT {
-                               return Err(SemanticError::InvalidAmount);
+                               return Err(Bolt12SemanticError::InvalidAmount);
                        }
                }
 
@@ -599,13 +600,13 @@ impl OfferContents {
                self.supported_quantity
        }
 
-       pub(super) fn check_quantity(&self, quantity: Option<u64>) -> Result<(), SemanticError> {
+       pub(super) fn check_quantity(&self, quantity: Option<u64>) -> Result<(), Bolt12SemanticError> {
                let expects_quantity = self.expects_quantity();
                match quantity {
-                       None if expects_quantity => Err(SemanticError::MissingQuantity),
-                       Some(_) if !expects_quantity => Err(SemanticError::UnexpectedQuantity),
+                       None if expects_quantity => Err(Bolt12SemanticError::MissingQuantity),
+                       Some(_) if !expects_quantity => Err(Bolt12SemanticError::UnexpectedQuantity),
                        Some(quantity) if !self.is_valid_quantity(quantity) => {
-                               Err(SemanticError::InvalidQuantity)
+                               Err(Bolt12SemanticError::InvalidQuantity)
                        },
                        _ => Ok(()),
                }
@@ -767,7 +768,7 @@ impl Bech32Encode for Offer {
 }
 
 impl FromStr for Offer {
-       type Err = ParseError;
+       type Err = Bolt12ParseError;
 
        fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
                Self::from_bech32_str(s)
@@ -775,7 +776,7 @@ impl FromStr for Offer {
 }
 
 impl TryFrom<Vec<u8>> for Offer {
-       type Error = ParseError;
+       type Error = Bolt12ParseError;
 
        fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
                let offer = ParsedMessage::<OfferTlvStream>::try_from(bytes)?;
@@ -786,7 +787,7 @@ impl TryFrom<Vec<u8>> for Offer {
 }
 
 impl TryFrom<OfferTlvStream> for OfferContents {
-       type Error = SemanticError;
+       type Error = Bolt12SemanticError;
 
        fn try_from(tlv_stream: OfferTlvStream) -> Result<Self, Self::Error> {
                let OfferTlvStream {
@@ -799,15 +800,15 @@ impl TryFrom<OfferTlvStream> for OfferContents {
                let amount = match (currency, amount) {
                        (None, None) => None,
                        (None, Some(amount_msats)) if amount_msats > MAX_VALUE_MSAT => {
-                               return Err(SemanticError::InvalidAmount);
+                               return Err(Bolt12SemanticError::InvalidAmount);
                        },
                        (None, Some(amount_msats)) => Some(Amount::Bitcoin { amount_msats }),
-                       (Some(_), None) => return Err(SemanticError::MissingAmount),
+                       (Some(_), None) => return Err(Bolt12SemanticError::MissingAmount),
                        (Some(iso4217_code), Some(amount)) => Some(Amount::Currency { iso4217_code, amount }),
                };
 
                let description = match description {
-                       None => return Err(SemanticError::MissingDescription),
+                       None => return Err(Bolt12SemanticError::MissingDescription),
                        Some(description) => description,
                };
 
@@ -823,7 +824,7 @@ impl TryFrom<OfferTlvStream> for OfferContents {
                };
 
                let signing_pubkey = match node_id {
-                       None => return Err(SemanticError::MissingSigningPubkey),
+                       None => return Err(Bolt12SemanticError::MissingSigningPubkey),
                        Some(node_id) => node_id,
                };
 
@@ -855,7 +856,7 @@ mod tests {
        use crate::ln::features::OfferFeatures;
        use crate::ln::inbound_payment::ExpandedKey;
        use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
-       use crate::offers::parse::{ParseError, SemanticError};
+       use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError};
        use crate::offers::test_utils::*;
        use crate::util::ser::{BigSize, Writeable};
        use crate::util::string::PrintableString;
@@ -1089,7 +1090,7 @@ mod tests {
                assert_eq!(tlv_stream.currency, Some(b"USD"));
                match builder.build() {
                        Ok(_) => panic!("expected error"),
-                       Err(e) => assert_eq!(e, SemanticError::UnsupportedCurrency),
+                       Err(e) => assert_eq!(e, Bolt12SemanticError::UnsupportedCurrency),
                }
 
                let offer = OfferBuilder::new("foo".into(), pubkey(42))
@@ -1104,7 +1105,7 @@ mod tests {
                let invalid_amount = Amount::Bitcoin { amount_msats: MAX_VALUE_MSAT + 1 };
                match OfferBuilder::new("foo".into(), pubkey(42)).amount(invalid_amount).build() {
                        Ok(_) => panic!("expected error"),
-                       Err(e) => assert_eq!(e, SemanticError::InvalidAmount),
+                       Err(e) => assert_eq!(e, Bolt12SemanticError::InvalidAmount),
                }
        }
 
@@ -1258,7 +1259,7 @@ mod tests {
                        .request_invoice(vec![1; 32], pubkey(43))
                {
                        Ok(_) => panic!("expected error"),
-                       Err(e) => assert_eq!(e, SemanticError::UnknownRequiredFeatures),
+                       Err(e) => assert_eq!(e, Bolt12SemanticError::UnknownRequiredFeatures),
                }
        }
 
@@ -1304,7 +1305,7 @@ mod tests {
 
                match Offer::try_from(encoded_offer) {
                        Ok(_) => panic!("expected error"),
-                       Err(e) => assert_eq!(e, ParseError::InvalidSemantics(SemanticError::MissingAmount)),
+                       Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount)),
                }
 
                let mut tlv_stream = offer.as_tlv_stream();
@@ -1316,7 +1317,7 @@ mod tests {
 
                match Offer::try_from(encoded_offer) {
                        Ok(_) => panic!("expected error"),
-                       Err(e) => assert_eq!(e, ParseError::InvalidSemantics(SemanticError::InvalidAmount)),
+                       Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount)),
                }
        }
 
@@ -1336,7 +1337,7 @@ mod tests {
                match Offer::try_from(encoded_offer) {
                        Ok(_) => panic!("expected error"),
                        Err(e) => {
-                               assert_eq!(e, ParseError::InvalidSemantics(SemanticError::MissingDescription));
+                               assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription));
                        },
                }
        }
@@ -1426,7 +1427,7 @@ mod tests {
                match Offer::try_from(encoded_offer) {
                        Ok(_) => panic!("expected error"),
                        Err(e) => {
-                               assert_eq!(e, ParseError::InvalidSemantics(SemanticError::MissingSigningPubkey));
+                               assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey));
                        },
                }
        }
@@ -1443,14 +1444,14 @@ mod tests {
 
                match Offer::try_from(encoded_offer) {
                        Ok(_) => panic!("expected error"),
-                       Err(e) => assert_eq!(e, ParseError::Decode(DecodeError::InvalidValue)),
+                       Err(e) => assert_eq!(e, Bolt12ParseError::Decode(DecodeError::InvalidValue)),
                }
        }
 }
 
 #[cfg(test)]
 mod bech32_tests {
-       use super::{Offer, ParseError};
+       use super::{Bolt12ParseError, Offer};
        use bitcoin::bech32;
        use crate::ln::msgs::DecodeError;
 
@@ -1492,7 +1493,7 @@ mod bech32_tests {
                for encoded_offer in &offers {
                        match encoded_offer.parse::<Offer>() {
                                Ok(_) => panic!("Valid offer: {}", encoded_offer),
-                               Err(e) => assert_eq!(e, ParseError::InvalidContinuation),
+                               Err(e) => assert_eq!(e, Bolt12ParseError::InvalidContinuation),
                        }
                }
 
@@ -1503,7 +1504,7 @@ mod bech32_tests {
                let encoded_offer = "lni1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxg";
                match encoded_offer.parse::<Offer>() {
                        Ok(_) => panic!("Valid offer: {}", encoded_offer),
-                       Err(e) => assert_eq!(e, ParseError::InvalidBech32Hrp),
+                       Err(e) => assert_eq!(e, Bolt12ParseError::InvalidBech32Hrp),
                }
        }
 
@@ -1512,7 +1513,7 @@ mod bech32_tests {
                let encoded_offer = "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxo";
                match encoded_offer.parse::<Offer>() {
                        Ok(_) => panic!("Valid offer: {}", encoded_offer),
-                       Err(e) => assert_eq!(e, ParseError::Bech32(bech32::Error::InvalidChar('o'))),
+                       Err(e) => assert_eq!(e, Bolt12ParseError::Bech32(bech32::Error::InvalidChar('o'))),
                }
        }
 
@@ -1521,7 +1522,7 @@ mod bech32_tests {
                let encoded_offer = "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxgqqqqq";
                match encoded_offer.parse::<Offer>() {
                        Ok(_) => panic!("Valid offer: {}", encoded_offer),
-                       Err(e) => assert_eq!(e, ParseError::Decode(DecodeError::InvalidValue)),
+                       Err(e) => assert_eq!(e, Bolt12ParseError::Decode(DecodeError::InvalidValue)),
                }
        }
 }