Merge pull request #2492 from optout21/payment-hash-display
[rust-lightning] / lightning / src / offers / refund.rs
index 8f91db597f62527ab52f9569ae8ce2182c53162f..d419e8fe0d2b41e06c8b44f5f6215d8d07a221a9 100644 (file)
 //! Data structures and encoding for refunds.
 //!
 //! A [`Refund`] is an "offer for money" and is typically constructed by a merchant and presented
-//! directly to the customer. The recipient responds with an [`Invoice`] to be paid.
+//! directly to the customer. The recipient responds with a [`Bolt12Invoice`] to be paid.
 //!
 //! This is an [`InvoiceRequest`] produced *not* in response to an [`Offer`].
 //!
-//! [`Invoice`]: crate::offers::invoice::Invoice
+//! [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
 //! [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
 //! [`Offer`]: crate::offers::offer::Offer
 //!
 //!
 //! use bitcoin::network::constants::Network;
 //! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
-//! use lightning::offers::parse::ParseError;
+//! use lightning::offers::parse::Bolt12ParseError;
 //! use lightning::offers::refund::{Refund, RefundBuilder};
 //! use lightning::util::ser::{Readable, Writeable};
 //!
-//! # use lightning::onion_message::BlindedPath;
+//! # use lightning::blinded_path::BlindedPath;
 //! # #[cfg(feature = "std")]
 //! # use std::time::SystemTime;
 //! #
@@ -40,7 +40,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);
@@ -78,20 +78,19 @@ use core::convert::TryFrom;
 use core::ops::Deref;
 use core::str::FromStr;
 use core::time::Duration;
-use crate::chain::keysinterface::EntropySource;
+use crate::sign::EntropySource;
 use crate::io;
+use crate::blinded_path::BlindedPath;
 use crate::ln::PaymentHash;
 use crate::ln::features::InvoiceRequestFeatures;
 use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce};
 use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
-use crate::offers::invoice::{BlindedPayInfo, InvoiceBuilder};
-use crate::offers::invoice_request::{INVOICE_REQUEST_PAYER_ID_TYPE, INVOICE_REQUEST_TYPES, InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef};
-use crate::offers::merkle::TlvStream;
-use crate::offers::offer::{OFFER_TYPES, OfferTlvStream, OfferTlvStreamRef};
-use crate::offers::parse::{Bech32Encode, ParseError, ParsedMessage, SemanticError};
-use crate::offers::payer::{PAYER_METADATA_TYPE, PayerContents, PayerTlvStream, PayerTlvStreamRef};
+use crate::offers::invoice::{BlindedPayInfo, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder};
+use crate::offers::invoice_request::{InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef};
+use crate::offers::offer::{OfferTlvStream, OfferTlvStreamRef};
+use crate::offers::parse::{Bech32Encode, Bolt12ParseError, Bolt12SemanticError, ParsedMessage};
+use crate::offers::payer::{PayerContents, PayerTlvStream, PayerTlvStreamRef};
 use crate::offers::signer::{Metadata, MetadataMaterial, self};
-use crate::onion_message::BlindedPath;
 use crate::util::ser::{SeekReadable, WithoutLength, Writeable, Writer};
 use crate::util::string::PrintableString;
 
@@ -100,12 +99,14 @@ use crate::prelude::*;
 #[cfg(feature = "std")]
 use std::time::SystemTime;
 
-const IV_BYTES: &[u8; IV_LEN] = b"LDK Refund ~~~~~";
+pub(super) const IV_BYTES: &[u8; IV_LEN] = b"LDK Refund ~~~~~";
 
 /// Builds a [`Refund`] for the "offer for money" flow.
 ///
 /// See [module-level documentation] for usage.
 ///
+/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+///
 /// [module-level documentation]: self
 pub struct RefundBuilder<'a, T: secp256k1::Signing> {
        refund: RefundContents,
@@ -116,13 +117,13 @@ impl<'a> RefundBuilder<'a, secp256k1::SignOnly> {
        /// Creates a new builder for a refund using the [`Refund::payer_id`] for the public node id to
        /// send to if no [`Refund::paths`] are set. Otherwise, it may be a transient pubkey.
        ///
-       /// Additionally, sets the required [`Refund::description`], [`Refund::metadata`], and
+       /// Additionally, sets the required [`Refund::description`], [`Refund::payer_metadata`], and
        /// [`Refund::amount_msats`].
        pub fn new(
                description: String, metadata: Vec<u8>, payer_id: PublicKey, amount_msats: u64
-       ) -> Result<Self, SemanticError> {
+       ) -> Result<Self, Bolt12SemanticError> {
                if amount_msats > MAX_VALUE_MSAT {
-                       return Err(SemanticError::InvalidAmount);
+                       return Err(Bolt12SemanticError::InvalidAmount);
                }
 
                let metadata = Metadata::Bytes(metadata);
@@ -151,9 +152,9 @@ impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> {
        pub fn deriving_payer_id<ES: Deref>(
                description: String, node_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES,
                secp_ctx: &'a Secp256k1<T>, amount_msats: u64
-       ) -> Result<Self, SemanticError> where ES::Target: EntropySource {
+       ) -> Result<Self, Bolt12SemanticError> where ES::Target: EntropySource {
                if amount_msats > MAX_VALUE_MSAT {
-                       return Err(SemanticError::InvalidAmount);
+                       return Err(Bolt12SemanticError::InvalidAmount);
                }
 
                let nonce = Nonce::from_entropy_source(entropy_source);
@@ -206,12 +207,12 @@ impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> {
        }
 
        /// Sets [`Refund::quantity`] of items. This is purely for informational purposes. It is useful
-       /// when the refund pertains to an [`Invoice`] that paid for more than one item from an
+       /// when the refund pertains to a [`Bolt12Invoice`] that paid for more than one item from an
        /// [`Offer`] as specified by [`InvoiceRequest::quantity`].
        ///
        /// Successive calls to this method will override the previous setting.
        ///
-       /// [`Invoice`]: crate::offers::invoice::Invoice
+       /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
        /// [`InvoiceRequest::quantity`]: crate::offers::invoice_request::InvoiceRequest::quantity
        /// [`Offer`]: crate::offers::offer::Offer
        pub fn quantity(mut self, quantity: u64) -> Self {
@@ -228,12 +229,12 @@ impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> {
        }
 
        /// Builds a [`Refund`] after checking for valid semantics.
-       pub fn build(mut self) -> Result<Refund, SemanticError> {
+       pub fn build(mut self) -> Result<Refund, Bolt12SemanticError> {
                if self.refund.chain() == self.refund.implied_chain() {
                        self.refund.chain = None;
                }
 
-               // Create the metadata for stateless verification of aInvoice.
+               // Create the metadata for stateless verification of a Bolt12Invoice.
                if self.refund.payer.0.has_derivation_material() {
                        let mut metadata = core::mem::take(&mut self.refund.payer.0);
 
@@ -271,13 +272,13 @@ impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> {
        }
 }
 
-/// A `Refund` is a request to send an [`Invoice`] without a preceding [`Offer`].
+/// A `Refund` is a request to send an [`Bolt12Invoice`] without a preceding [`Offer`].
 ///
 /// Typically, after an invoice is paid, the recipient may publish a refund allowing the sender to
 /// recoup their funds. A refund may be used more generally as an "offer for money", such as with a
 /// bitcoin ATM.
 ///
-/// [`Invoice`]: crate::offers::invoice::Invoice
+/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
 /// [`Offer`]: crate::offers::offer::Offer
 #[derive(Clone, Debug)]
 #[cfg_attr(test, derive(PartialEq))]
@@ -286,9 +287,9 @@ pub struct Refund {
        pub(super) contents: RefundContents,
 }
 
-/// The contents of a [`Refund`], which may be shared with an [`Invoice`].
+/// The contents of a [`Refund`], which may be shared with an [`Bolt12Invoice`].
 ///
-/// [`Invoice`]: crate::offers::invoice::Invoice
+/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
 #[derive(Clone, Debug)]
 #[cfg_attr(test, derive(PartialEq))]
 pub(super) struct RefundContents {
@@ -311,14 +312,14 @@ 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.
        ///
        /// If `None`, the refund does not expire.
        pub fn absolute_expiry(&self) -> Option<Duration> {
-               self.contents.absolute_expiry
+               self.contents.absolute_expiry()
        }
 
        /// Whether the refund has expired.
@@ -330,43 +331,43 @@ impl Refund {
        /// The issuer of the refund, possibly beginning with `user@domain` or `domain`. Intended to be
        /// displayed to the user but with the caveat that it has not been verified in any way.
        pub fn issuer(&self) -> Option<PrintableString> {
-               self.contents.issuer.as_ref().map(|issuer| PrintableString(issuer.as_str()))
+               self.contents.issuer()
        }
 
        /// Paths to the sender originating from publicly reachable nodes. Blinded paths provide sender
        /// privacy by obfuscating its node id.
        pub fn paths(&self) -> &[BlindedPath] {
-               self.contents.paths.as_ref().map(|paths| paths.as_slice()).unwrap_or(&[])
+               self.contents.paths()
        }
 
        /// An unpredictable series of bytes, typically containing information about the derivation of
        /// [`payer_id`].
        ///
        /// [`payer_id`]: Self::payer_id
-       pub fn metadata(&self) -> &[u8] {
+       pub fn payer_metadata(&self) -> &[u8] {
                self.contents.metadata()
        }
 
        /// A chain that the refund is valid for.
        pub fn chain(&self) -> ChainHash {
-               self.contents.chain.unwrap_or_else(|| self.contents.implied_chain())
+               self.contents.chain()
        }
 
        /// The amount to refund in msats (i.e., the minimum lightning-payable unit for [`chain`]).
        ///
        /// [`chain`]: Self::chain
        pub fn amount_msats(&self) -> u64 {
-               self.contents.amount_msats
+               self.contents.amount_msats()
        }
 
        /// Features pertaining to requesting an invoice.
        pub fn features(&self) -> &InvoiceRequestFeatures {
-               &self.contents.features
+               &self.contents.features()
        }
 
        /// The quantity of an item that refund is for.
        pub fn quantity(&self) -> Option<u64> {
-               self.contents.quantity
+               self.contents.quantity()
        }
 
        /// A public node id to send to in the case where there are no [`paths`]. Otherwise, a possibly
@@ -374,12 +375,12 @@ impl Refund {
        ///
        /// [`paths`]: Self::paths
        pub fn payer_id(&self) -> PublicKey {
-               self.contents.payer_id
+               self.contents.payer_id()
        }
 
        /// Payer provided note to include in the invoice.
        pub fn payer_note(&self) -> Option<PrintableString> {
-               self.contents.payer_note.as_ref().map(|payer_note| PrintableString(payer_note.as_str()))
+               self.contents.payer_note()
        }
 
        /// Creates an [`InvoiceBuilder`] for the refund with the given required fields and using the
@@ -388,12 +389,14 @@ impl Refund {
        /// See [`Refund::respond_with_no_std`] for further details where the aforementioned creation
        /// time is used for the `created_at` parameter.
        ///
+       /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+       ///
        /// [`Duration`]: core::time::Duration
        #[cfg(feature = "std")]
        pub fn respond_with(
-               &self, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, payment_hash: PaymentHash,
+               &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
                signing_pubkey: PublicKey,
-       ) -> Result<InvoiceBuilderSemanticError> {
+       ) -> Result<InvoiceBuilder<ExplicitSigningPubkey>, Bolt12SemanticError> {
                let created_at = std::time::SystemTime::now()
                        .duration_since(std::time::SystemTime::UNIX_EPOCH)
                        .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
@@ -404,8 +407,8 @@ impl Refund {
        /// Creates an [`InvoiceBuilder`] for the refund with the given required fields.
        ///
        /// Unless [`InvoiceBuilder::relative_expiry`] is set, the invoice will expire two hours after
-       /// `created_at`, which is used to set [`Invoice::created_at`]. Useful for `no-std` builds where
-       /// [`std::time::SystemTime`] is not available.
+       /// `created_at`, which is used to set [`Bolt12Invoice::created_at`]. Useful for `no-std` builds
+       /// where [`std::time::SystemTime`] is not available.
        ///
        /// The caller is expected to remember the preimage of `payment_hash` in order to
        /// claim a payment for the invoice.
@@ -420,18 +423,69 @@ impl Refund {
        ///
        /// Errors if the request contains unknown required features.
        ///
-       /// [`Invoice::created_at`]: crate::offers::invoice::Invoice::created_at
+       /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+       ///
+       /// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
        pub fn respond_with_no_std(
-               &self, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, payment_hash: PaymentHash,
+               &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
                signing_pubkey: PublicKey, created_at: Duration
-       ) -> Result<InvoiceBuilderSemanticError> {
+       ) -> Result<InvoiceBuilder<ExplicitSigningPubkey>, Bolt12SemanticError> {
                if self.features().requires_unknown_bits() {
-                       return Err(SemanticError::UnknownRequiredFeatures);
+                       return Err(Bolt12SemanticError::UnknownRequiredFeatures);
                }
 
                InvoiceBuilder::for_refund(self, payment_paths, created_at, payment_hash, signing_pubkey)
        }
 
+       /// Creates an [`InvoiceBuilder`] for the refund using the given required fields and that uses
+       /// derived signing keys to sign the [`Bolt12Invoice`].
+       ///
+       /// See [`Refund::respond_with`] for further details.
+       ///
+       /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+       ///
+       /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
+       #[cfg(feature = "std")]
+       pub fn respond_using_derived_keys<ES: Deref>(
+               &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
+               expanded_key: &ExpandedKey, entropy_source: ES
+       ) -> Result<InvoiceBuilder<DerivedSigningPubkey>, Bolt12SemanticError>
+       where
+               ES::Target: EntropySource,
+       {
+               let created_at = std::time::SystemTime::now()
+                       .duration_since(std::time::SystemTime::UNIX_EPOCH)
+                       .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
+
+               self.respond_using_derived_keys_no_std(
+                       payment_paths, payment_hash, created_at, expanded_key, entropy_source
+               )
+       }
+
+       /// Creates an [`InvoiceBuilder`] for the refund using the given required fields and that uses
+       /// derived signing keys to sign the [`Bolt12Invoice`].
+       ///
+       /// See [`Refund::respond_with_no_std`] for further details.
+       ///
+       /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
+       ///
+       /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
+       pub fn respond_using_derived_keys_no_std<ES: Deref>(
+               &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
+               created_at: core::time::Duration, expanded_key: &ExpandedKey, entropy_source: ES
+       ) -> Result<InvoiceBuilder<DerivedSigningPubkey>, Bolt12SemanticError>
+       where
+               ES::Target: EntropySource,
+       {
+               if self.features().requires_unknown_bits() {
+                       return Err(Bolt12SemanticError::UnknownRequiredFeatures);
+               }
+
+               let nonce = Nonce::from_entropy_source(entropy_source);
+               let keys = signer::derive_keys(nonce, expanded_key);
+               InvoiceBuilder::for_refund_using_keys(self, payment_paths, created_at, payment_hash, keys)
+       }
+
        #[cfg(test)]
        fn as_tlv_stream(&self) -> RefundTlvStreamRef {
                self.contents.as_tlv_stream()
@@ -445,6 +499,14 @@ impl AsRef<[u8]> for Refund {
 }
 
 impl RefundContents {
+       pub fn description(&self) -> PrintableString {
+               PrintableString(&self.description)
+       }
+
+       pub fn absolute_expiry(&self) -> Option<Duration> {
+               self.absolute_expiry
+       }
+
        #[cfg(feature = "std")]
        pub(super) fn is_expired(&self) -> bool {
                match self.absolute_expiry {
@@ -456,7 +518,15 @@ impl RefundContents {
                }
        }
 
-       fn metadata(&self) -> &[u8] {
+       pub fn issuer(&self) -> Option<PrintableString> {
+               self.issuer.as_ref().map(|issuer| PrintableString(issuer.as_str()))
+       }
+
+       pub fn paths(&self) -> &[BlindedPath] {
+               self.paths.as_ref().map(|paths| paths.as_slice()).unwrap_or(&[])
+       }
+
+       pub(super) fn metadata(&self) -> &[u8] {
                self.payer.0.as_bytes().map(|bytes| bytes.as_slice()).unwrap_or(&[])
        }
 
@@ -468,20 +538,35 @@ impl RefundContents {
                ChainHash::using_genesis_block(Network::Bitcoin)
        }
 
-       /// Verifies that the payer metadata was produced from the refund in the TLV stream.
-       pub(super) fn verify<T: secp256k1::Signing>(
-               &self, tlv_stream: TlvStream<'_>, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
-       ) -> bool {
-               let offer_records = tlv_stream.clone().range(OFFER_TYPES);
-               let invreq_records = tlv_stream.range(INVOICE_REQUEST_TYPES).filter(|record| {
-                       match record.r#type {
-                               PAYER_METADATA_TYPE => false, // Should be outside range
-                               INVOICE_REQUEST_PAYER_ID_TYPE => !self.payer.0.derives_keys(),
-                               _ => true,
-                       }
-               });
-               let tlv_stream = offer_records.chain(invreq_records);
-               signer::verify_metadata(self.metadata(), key, IV_BYTES, self.payer_id, tlv_stream, secp_ctx)
+       pub fn amount_msats(&self) -> u64 {
+               self.amount_msats
+       }
+
+       /// Features pertaining to requesting an invoice.
+       pub fn features(&self) -> &InvoiceRequestFeatures {
+               &self.features
+       }
+
+       /// The quantity of an item that refund is for.
+       pub fn quantity(&self) -> Option<u64> {
+               self.quantity
+       }
+
+       /// A public node id to send to in the case where there are no [`paths`]. Otherwise, a possibly
+       /// transient pubkey.
+       ///
+       /// [`paths`]: Self::paths
+       pub fn payer_id(&self) -> PublicKey {
+               self.payer_id
+       }
+
+       /// Payer provided note to include in the invoice.
+       pub fn payer_note(&self) -> Option<PrintableString> {
+               self.payer_note.as_ref().map(|payer_note| PrintableString(payer_note.as_str()))
+       }
+
+       pub(super) fn derives_keys(&self) -> bool {
+               self.payer.0.derives_keys()
        }
 
        pub(super) fn as_tlv_stream(&self) -> RefundTlvStreamRef {
@@ -556,7 +641,7 @@ impl Bech32Encode for Refund {
 }
 
 impl FromStr for Refund {
-       type Err = ParseError;
+       type Err = Bolt12ParseError;
 
        fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
                Refund::from_bech32_str(s)
@@ -564,7 +649,7 @@ impl FromStr for Refund {
 }
 
 impl TryFrom<Vec<u8>> for Refund {
-       type Error = ParseError;
+       type Error = Bolt12ParseError;
 
        fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
                let refund = ParsedMessage::<RefundTlvStream>::try_from(bytes)?;
@@ -576,7 +661,7 @@ impl TryFrom<Vec<u8>> for Refund {
 }
 
 impl TryFrom<RefundTlvStream> for RefundContents {
-       type Error = SemanticError;
+       type Error = Bolt12SemanticError;
 
        fn try_from(tlv_stream: RefundTlvStream) -> Result<Self, Self::Error> {
                let (
@@ -589,45 +674,45 @@ impl TryFrom<RefundTlvStream> for RefundContents {
                ) = tlv_stream;
 
                let payer = match payer_metadata {
-                       None => return Err(SemanticError::MissingPayerMetadata),
+                       None => return Err(Bolt12SemanticError::MissingPayerMetadata),
                        Some(metadata) => PayerContents(Metadata::Bytes(metadata)),
                };
 
                if metadata.is_some() {
-                       return Err(SemanticError::UnexpectedMetadata);
+                       return Err(Bolt12SemanticError::UnexpectedMetadata);
                }
 
                if chains.is_some() {
-                       return Err(SemanticError::UnexpectedChain);
+                       return Err(Bolt12SemanticError::UnexpectedChain);
                }
 
                if currency.is_some() || offer_amount.is_some() {
-                       return Err(SemanticError::UnexpectedAmount);
+                       return Err(Bolt12SemanticError::UnexpectedAmount);
                }
 
                let description = match description {
-                       None => return Err(SemanticError::MissingDescription),
+                       None => return Err(Bolt12SemanticError::MissingDescription),
                        Some(description) => description,
                };
 
                if offer_features.is_some() {
-                       return Err(SemanticError::UnexpectedFeatures);
+                       return Err(Bolt12SemanticError::UnexpectedFeatures);
                }
 
                let absolute_expiry = absolute_expiry.map(Duration::from_secs);
 
                if quantity_max.is_some() {
-                       return Err(SemanticError::UnexpectedQuantity);
+                       return Err(Bolt12SemanticError::UnexpectedQuantity);
                }
 
                if node_id.is_some() {
-                       return Err(SemanticError::UnexpectedSigningPubkey);
+                       return Err(Bolt12SemanticError::UnexpectedSigningPubkey);
                }
 
                let amount_msats = match amount {
-                       None => return Err(SemanticError::MissingAmount),
+                       None => return Err(Bolt12SemanticError::MissingAmount),
                        Some(amount_msats) if amount_msats > MAX_VALUE_MSAT => {
-                               return Err(SemanticError::InvalidAmount);
+                               return Err(Bolt12SemanticError::InvalidAmount);
                        },
                        Some(amount_msats) => amount_msats,
                };
@@ -635,7 +720,7 @@ impl TryFrom<RefundTlvStream> for RefundContents {
                let features = features.unwrap_or_else(InvoiceRequestFeatures::empty);
 
                let payer_id = match payer_id {
-                       None => return Err(SemanticError::MissingPayerId),
+                       None => return Err(Bolt12SemanticError::MissingPayerId),
                        Some(payer_id) => payer_id,
                };
 
@@ -661,16 +746,16 @@ mod tests {
        use bitcoin::secp256k1::{KeyPair, Secp256k1, SecretKey};
        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::{InvoiceRequestFeatures, OfferFeatures};
        use crate::ln::inbound_payment::ExpandedKey;
        use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
        use crate::offers::invoice_request::InvoiceRequestTlvStreamRef;
        use crate::offers::offer::OfferTlvStreamRef;
-       use crate::offers::parse::{ParseError, SemanticError};
+       use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError};
        use crate::offers::payer::PayerTlvStreamRef;
        use crate::offers::test_utils::*;
-       use crate::onion_message::{BlindedHop, BlindedPath};
        use crate::util::ser::{BigSize, Writeable};
        use crate::util::string::PrintableString;
 
@@ -695,7 +780,7 @@ mod tests {
                refund.write(&mut buffer).unwrap();
 
                assert_eq!(refund.bytes, buffer.as_slice());
-               assert_eq!(refund.metadata(), &[1; 32]);
+               assert_eq!(refund.payer_metadata(), &[1; 32]);
                assert_eq!(refund.description(), PrintableString("foo"));
                assert_eq!(refund.absolute_expiry(), None);
                #[cfg(feature = "std")]
@@ -745,7 +830,7 @@ mod tests {
        fn fails_building_refund_with_invalid_amount() {
                match RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), MAX_VALUE_MSAT + 1) {
                        Ok(_) => panic!("expected error"),
-                       Err(e) => assert_eq!(e, SemanticError::InvalidAmount),
+                       Err(e) => assert_eq!(e, Bolt12SemanticError::InvalidAmount),
                }
        }
 
@@ -1014,7 +1099,7 @@ mod tests {
                        .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now())
                {
                        Ok(_) => panic!("expected error"),
-                       Err(e) => assert_eq!(e, SemanticError::UnknownRequiredFeatures),
+                       Err(e) => assert_eq!(e, Bolt12SemanticError::UnknownRequiredFeatures),
                }
        }
 
@@ -1032,7 +1117,7 @@ mod tests {
                match Refund::try_from(tlv_stream.to_bytes()) {
                        Ok(_) => panic!("expected error"),
                        Err(e) => {
-                               assert_eq!(e, ParseError::InvalidSemantics(SemanticError::MissingPayerMetadata));
+                               assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerMetadata));
                        },
                }
        }
@@ -1051,7 +1136,7 @@ mod tests {
                match Refund::try_from(tlv_stream.to_bytes()) {
                        Ok(_) => panic!("expected error"),
                        Err(e) => {
-                               assert_eq!(e, ParseError::InvalidSemantics(SemanticError::MissingDescription));
+                               assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription));
                        },
                }
        }
@@ -1070,7 +1155,7 @@ mod tests {
                match Refund::try_from(tlv_stream.to_bytes()) {
                        Ok(_) => panic!("expected error"),
                        Err(e) => {
-                               assert_eq!(e, ParseError::InvalidSemantics(SemanticError::MissingAmount));
+                               assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount));
                        },
                }
 
@@ -1080,7 +1165,7 @@ mod tests {
                match Refund::try_from(tlv_stream.to_bytes()) {
                        Ok(_) => panic!("expected error"),
                        Err(e) => {
-                               assert_eq!(e, ParseError::InvalidSemantics(SemanticError::InvalidAmount));
+                               assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount));
                        },
                }
        }
@@ -1099,7 +1184,7 @@ mod tests {
                match Refund::try_from(tlv_stream.to_bytes()) {
                        Ok(_) => panic!("expected error"),
                        Err(e) => {
-                               assert_eq!(e, ParseError::InvalidSemantics(SemanticError::MissingPayerId));
+                               assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerId));
                        },
                }
        }
@@ -1168,7 +1253,7 @@ mod tests {
                match Refund::try_from(tlv_stream.to_bytes()) {
                        Ok(_) => panic!("expected error"),
                        Err(e) => {
-                               assert_eq!(e, ParseError::InvalidSemantics(SemanticError::UnexpectedMetadata));
+                               assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedMetadata));
                        },
                }
 
@@ -1179,7 +1264,7 @@ mod tests {
                match Refund::try_from(tlv_stream.to_bytes()) {
                        Ok(_) => panic!("expected error"),
                        Err(e) => {
-                               assert_eq!(e, ParseError::InvalidSemantics(SemanticError::UnexpectedChain));
+                               assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedChain));
                        },
                }
 
@@ -1190,7 +1275,7 @@ mod tests {
                match Refund::try_from(tlv_stream.to_bytes()) {
                        Ok(_) => panic!("expected error"),
                        Err(e) => {
-                               assert_eq!(e, ParseError::InvalidSemantics(SemanticError::UnexpectedAmount));
+                               assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedAmount));
                        },
                }
 
@@ -1201,7 +1286,7 @@ mod tests {
                match Refund::try_from(tlv_stream.to_bytes()) {
                        Ok(_) => panic!("expected error"),
                        Err(e) => {
-                               assert_eq!(e, ParseError::InvalidSemantics(SemanticError::UnexpectedFeatures));
+                               assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedFeatures));
                        },
                }
 
@@ -1211,7 +1296,7 @@ mod tests {
                match Refund::try_from(tlv_stream.to_bytes()) {
                        Ok(_) => panic!("expected error"),
                        Err(e) => {
-                               assert_eq!(e, ParseError::InvalidSemantics(SemanticError::UnexpectedQuantity));
+                               assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedQuantity));
                        },
                }
 
@@ -1222,7 +1307,7 @@ mod tests {
                match Refund::try_from(tlv_stream.to_bytes()) {
                        Ok(_) => panic!("expected error"),
                        Err(e) => {
-                               assert_eq!(e, ParseError::InvalidSemantics(SemanticError::UnexpectedSigningPubkey));
+                               assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedSigningPubkey));
                        },
                }
        }
@@ -1242,7 +1327,7 @@ mod tests {
 
                match Refund::try_from(encoded_refund) {
                        Ok(_) => panic!("expected error"),
-                       Err(e) => assert_eq!(e, ParseError::Decode(DecodeError::InvalidValue)),
+                       Err(e) => assert_eq!(e, Bolt12ParseError::Decode(DecodeError::InvalidValue)),
                }
        }
 }