Move common BOLT 12 accessor methods to new macro.
[rust-lightning] / lightning / src / offers / invoice.rs
index 01aae89138ff9a8ce9a18a595dafa28e96d3df8d..7fdbab3379c3e59f6bc0f671f168a4b2b1ec76b1 100644 (file)
@@ -21,7 +21,7 @@
 //! extern crate lightning;
 //!
 //! use bitcoin::hashes::Hash;
-//! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
+//! use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey};
 //! use core::convert::TryFrom;
 //! use lightning::offers::invoice::UnsignedBolt12Invoice;
 //! use lightning::offers::invoice_request::InvoiceRequest;
@@ -39,7 +39,7 @@
 //! let payment_paths = create_payment_paths();
 //! let payment_hash = create_payment_hash();
 //! let secp_ctx = Secp256k1::new();
-//! let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32])?);
+//! let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32])?);
 //! let pubkey = PublicKey::from(keys);
 //! let wpubkey_hash = bitcoin::key::PublicKey::new(pubkey).wpubkey_hash().unwrap();
 //! let mut buffer = Vec::new();
@@ -71,7 +71,7 @@
 //! # let payment_paths = create_payment_paths();
 //! # let payment_hash = create_payment_hash();
 //! # let secp_ctx = Secp256k1::new();
-//! # let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32])?);
+//! # let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32])?);
 //! # let pubkey = PublicKey::from(keys);
 //! # let wpubkey_hash = bitcoin::key::PublicKey::new(pubkey).wpubkey_hash().unwrap();
 //! # let mut buffer = Vec::new();
 //!
 //! ```
 
+use bitcoin::{WitnessProgram, Network, WitnessVersion};
 use bitcoin::blockdata::constants::ChainHash;
-use bitcoin::hash_types::{WPubkeyHash, WScriptHash};
-use bitcoin::network::constants::Network;
-use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, self};
+use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, self};
 use bitcoin::secp256k1::schnorr::Signature;
-use bitcoin::address::{Address, Payload, WitnessProgram, WitnessVersion};
-use bitcoin::key::TweakedPublicKey;
+use bitcoin::address::{Address, Payload};
 use core::time::Duration;
 use core::hash::{Hash, Hasher};
 use crate::io;
@@ -118,6 +116,7 @@ use crate::ln::channelmanager::PaymentId;
 use crate::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures, InvoiceRequestFeatures, OfferFeatures};
 use crate::ln::inbound_payment::ExpandedKey;
 use crate::ln::msgs::DecodeError;
+use crate::offers::invoice_macros::{invoice_accessors_common, invoice_builder_methods_common};
 use crate::offers::invoice_request::{INVOICE_REQUEST_PAYER_ID_TYPE, INVOICE_REQUEST_TYPES, IV_BYTES as INVOICE_REQUEST_IV_BYTES, InvoiceRequest, InvoiceRequestContents, InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef};
 use crate::offers::merkle::{SignError, SignFn, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, TlvStream, WithoutSignatures, self};
 use crate::offers::offer::{Amount, OFFER_TYPES, OfferTlvStream, OfferTlvStreamRef, Quantity};
@@ -201,7 +200,7 @@ pub struct ExplicitSigningPubkey {}
 /// [`Bolt12Invoice::signing_pubkey`] was derived.
 ///
 /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
-pub struct DerivedSigningPubkey(KeyPair);
+pub struct DerivedSigningPubkey(Keypair);
 
 impl SigningPubkeyStrategy for ExplicitSigningPubkey {}
 impl SigningPubkeyStrategy for DerivedSigningPubkey {}
@@ -268,7 +267,7 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { ($self: ident, $se
        #[cfg_attr(c_bindings, allow(dead_code))]
        pub(super) fn for_offer_using_keys(
                invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>,
-               created_at: Duration, payment_hash: PaymentHash, keys: KeyPair
+               created_at: Duration, payment_hash: PaymentHash, keys: Keypair
        ) -> Result<Self, Bolt12SemanticError> {
                let amount_msats = Self::amount_msats(invoice_request)?;
                let signing_pubkey = keys.public_key();
@@ -285,7 +284,7 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { ($self: ident, $se
        #[cfg_attr(c_bindings, allow(dead_code))]
        pub(super) fn for_refund_using_keys(
                refund: &'a Refund, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, created_at: Duration,
-               payment_hash: PaymentHash, keys: KeyPair,
+               payment_hash: PaymentHash, keys: Keypair,
        ) -> Result<Self, Bolt12SemanticError> {
                let amount_msats = refund.amount_msats();
                let signing_pubkey = keys.public_key();
@@ -372,65 +371,6 @@ macro_rules! invoice_builder_methods { (
 
                Ok(Self { invreq_bytes, invoice: contents, signing_pubkey_strategy })
        }
-
-       /// Sets the [`Bolt12Invoice::relative_expiry`] as seconds since [`Bolt12Invoice::created_at`].
-       /// Any expiry that has already passed is valid and can be checked for using
-       /// [`Bolt12Invoice::is_expired`].
-       ///
-       /// Successive calls to this method will override the previous setting.
-       pub fn relative_expiry($($self_mut)* $self: $self_type, relative_expiry_secs: u32) -> $return_type {
-               let relative_expiry = Duration::from_secs(relative_expiry_secs as u64);
-               $self.invoice.fields_mut().relative_expiry = Some(relative_expiry);
-               $return_value
-       }
-
-       /// Adds a P2WSH address to [`Bolt12Invoice::fallbacks`].
-       ///
-       /// Successive calls to this method will add another address. Caller is responsible for not
-       /// adding duplicate addresses and only calling if capable of receiving to P2WSH addresses.
-       pub fn fallback_v0_p2wsh($($self_mut)* $self: $self_type, script_hash: &WScriptHash) -> $return_type {
-               use bitcoin::hashes::Hash;
-               let address = FallbackAddress {
-                       version: WitnessVersion::V0.to_num(),
-                       program: Vec::from(script_hash.to_byte_array()),
-               };
-               $self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
-               $return_value
-       }
-
-       /// Adds a P2WPKH address to [`Bolt12Invoice::fallbacks`].
-       ///
-       /// Successive calls to this method will add another address. Caller is responsible for not
-       /// adding duplicate addresses and only calling if capable of receiving to P2WPKH addresses.
-       pub fn fallback_v0_p2wpkh($($self_mut)* $self: $self_type, pubkey_hash: &WPubkeyHash) -> $return_type {
-               use bitcoin::hashes::Hash;
-               let address = FallbackAddress {
-                       version: WitnessVersion::V0.to_num(),
-                       program: Vec::from(pubkey_hash.to_byte_array()),
-               };
-               $self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
-               $return_value
-       }
-
-       /// Adds a P2TR address to [`Bolt12Invoice::fallbacks`].
-       ///
-       /// Successive calls to this method will add another address. Caller is responsible for not
-       /// adding duplicate addresses and only calling if capable of receiving to P2TR addresses.
-       pub fn fallback_v1_p2tr_tweaked($($self_mut)* $self: $self_type, output_key: &TweakedPublicKey) -> $return_type {
-               let address = FallbackAddress {
-                       version: WitnessVersion::V1.to_num(),
-                       program: Vec::from(&output_key.serialize()[..]),
-               };
-               $self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
-               $return_value
-       }
-
-       /// Sets [`Bolt12Invoice::invoice_features`] to indicate MPP may be used. Otherwise, MPP is
-       /// disallowed.
-       pub fn allow_mpp($($self_mut)* $self: $self_type) -> $return_type {
-               $self.invoice.fields_mut().features.set_basic_mpp_optional();
-               $return_value
-       }
 } }
 
 impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> {
@@ -443,30 +383,35 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
 
 impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> {
        invoice_builder_methods!(self, Self, Self, self, S, mut);
+       invoice_builder_methods_common!(self, Self, self.invoice.fields_mut(), Self, self, S, mut);
 }
 
 #[cfg(all(c_bindings, not(test)))]
 impl<'a> InvoiceWithExplicitSigningPubkeyBuilder<'a> {
        invoice_explicit_signing_pubkey_builder_methods!(self, &mut Self);
        invoice_builder_methods!(self, &mut Self, (), (), ExplicitSigningPubkey);
+       invoice_builder_methods_common!(self, &mut Self, self.invoice.fields_mut(), (), (), ExplicitSigningPubkey);
 }
 
 #[cfg(all(c_bindings, test))]
 impl<'a> InvoiceWithExplicitSigningPubkeyBuilder<'a> {
        invoice_explicit_signing_pubkey_builder_methods!(self, &mut Self);
        invoice_builder_methods!(self, &mut Self, &mut Self, self, ExplicitSigningPubkey);
+       invoice_builder_methods_common!(self, &mut Self, self.invoice.fields_mut(), &mut Self, self, ExplicitSigningPubkey);
 }
 
 #[cfg(all(c_bindings, not(test)))]
 impl<'a> InvoiceWithDerivedSigningPubkeyBuilder<'a> {
        invoice_derived_signing_pubkey_builder_methods!(self, &mut Self);
        invoice_builder_methods!(self, &mut Self, (), (), DerivedSigningPubkey);
+       invoice_builder_methods_common!(self, &mut Self, self.invoice.fields_mut(), (), (), DerivedSigningPubkey);
 }
 
 #[cfg(all(c_bindings, test))]
 impl<'a> InvoiceWithDerivedSigningPubkeyBuilder<'a> {
        invoice_derived_signing_pubkey_builder_methods!(self, &mut Self);
        invoice_builder_methods!(self, &mut Self, &mut Self, self, DerivedSigningPubkey);
+       invoice_builder_methods_common!(self, &mut Self, self.invoice.fields_mut(), &mut Self, self, DerivedSigningPubkey);
 }
 
 #[cfg(c_bindings)]
@@ -503,6 +448,7 @@ for InvoiceBuilder<'a, DerivedSigningPubkey> {
 ///
 /// This is serialized as a TLV stream, which includes TLV records from the originating message. As
 /// such, it may include unknown, odd TLV records.
+#[derive(Clone)]
 pub struct UnsignedBolt12Invoice {
        bytes: Vec<u8>,
        contents: InvoiceContents,
@@ -697,7 +643,7 @@ macro_rules! invoice_accessors { ($self: ident, $contents: expr) => {
        ///
        /// [`Offer`]: crate::offers::offer::Offer
        /// [`Offer::amount`]: crate::offers::offer::Offer::amount
-       pub fn amount(&$self) -> Option<&Amount> {
+       pub fn amount(&$self) -> Option<Amount> {
                $contents.amount()
        }
 
@@ -717,7 +663,7 @@ macro_rules! invoice_accessors { ($self: ident, $contents: expr) => {
        /// From [`Offer::description`] or [`Refund::description`].
        ///
        /// [`Offer::description`]: crate::offers::offer::Offer::description
-       pub fn description(&$self) -> PrintableString {
+       pub fn description(&$self) -> Option<PrintableString> {
                $contents.description()
        }
 
@@ -794,35 +740,6 @@ macro_rules! invoice_accessors { ($self: ident, $contents: expr) => {
                $contents.payer_note()
        }
 
-       /// Paths to the recipient originating from publicly reachable nodes, including information
-       /// needed for routing payments across them.
-       ///
-       /// Blinded paths provide recipient privacy by obfuscating its node id. Note, however, that this
-       /// privacy is lost if a public node id is used for [`Bolt12Invoice::signing_pubkey`].
-       ///
-       /// This is not exported to bindings users as slices with non-reference types cannot be ABI
-       /// matched in another language.
-       pub fn payment_paths(&$self) -> &[(BlindedPayInfo, BlindedPath)] {
-               $contents.payment_paths()
-       }
-
-       /// Duration since the Unix epoch when the invoice was created.
-       pub fn created_at(&$self) -> Duration {
-               $contents.created_at()
-       }
-
-       /// Duration since [`Bolt12Invoice::created_at`] when the invoice has expired and therefore
-       /// should no longer be paid.
-       pub fn relative_expiry(&$self) -> Duration {
-               $contents.relative_expiry()
-       }
-
-       /// Whether the invoice has expired.
-       #[cfg(feature = "std")]
-       pub fn is_expired(&$self) -> bool {
-               $contents.is_expired()
-       }
-
        /// SHA256 hash of the payment preimage that will be given in return for paying the invoice.
        pub fn payment_hash(&$self) -> PaymentHash {
                $contents.payment_hash()
@@ -832,29 +749,15 @@ macro_rules! invoice_accessors { ($self: ident, $contents: expr) => {
        pub fn amount_msats(&$self) -> u64 {
                $contents.amount_msats()
        }
-
-       /// Fallback addresses for paying the invoice on-chain, in order of most-preferred to
-       /// least-preferred.
-       pub fn fallbacks(&$self) -> Vec<Address> {
-               $contents.fallbacks()
-       }
-
-       /// Features pertaining to paying an invoice.
-       pub fn invoice_features(&$self) -> &Bolt12InvoiceFeatures {
-               $contents.features()
-       }
-
-       /// The public key corresponding to the key used to sign the invoice.
-       pub fn signing_pubkey(&$self) -> PublicKey {
-               $contents.signing_pubkey()
-       }
 } }
 
 impl UnsignedBolt12Invoice {
+       invoice_accessors_common!(self, self.contents);
        invoice_accessors!(self, self.contents);
 }
 
 impl Bolt12Invoice {
+       invoice_accessors_common!(self, self.contents);
        invoice_accessors!(self, self.contents);
 
        /// Signature of the invoice verified using [`Bolt12Invoice::signing_pubkey`].
@@ -944,7 +847,7 @@ impl InvoiceContents {
                }
        }
 
-       fn amount(&self) -> Option<&Amount> {
+       fn amount(&self) -> Option<Amount> {
                match self {
                        InvoiceContents::ForOffer { invoice_request, .. } =>
                                invoice_request.inner.offer.amount(),
@@ -952,12 +855,12 @@ impl InvoiceContents {
                }
        }
 
-       fn description(&self) -> PrintableString {
+       fn description(&self) -> Option<PrintableString> {
                match self {
                        InvoiceContents::ForOffer { invoice_request, .. } => {
                                invoice_request.inner.offer.description()
                        },
-                       InvoiceContents::ForRefund { refund, .. } => refund.description(),
+                       InvoiceContents::ForRefund { refund, .. } => Some(refund.description()),
                }
        }
 
@@ -1093,8 +996,8 @@ impl InvoiceContents {
                                Err(_) => return None,
                        };
 
-                       let program = &address.program;
-                       let witness_program = match WitnessProgram::new(version, program.clone()) {
+                       let program = address.program.clone();
+                       let witness_program = match WitnessProgram::new(version, program) {
                                Ok(witness_program) => witness_program,
                                Err(_) => return None,
                        };
@@ -1473,12 +1376,13 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
 mod tests {
        use super::{Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, FallbackAddress, FullInvoiceTlvStreamRef, InvoiceTlvStreamRef, SIGNATURE_TAG, UnsignedBolt12Invoice};
 
+       use bitcoin::{WitnessProgram, WitnessVersion};
        use bitcoin::blockdata::constants::ChainHash;
        use bitcoin::blockdata::script::ScriptBuf;
        use bitcoin::hashes::Hash;
-       use bitcoin::network::constants::Network;
-       use bitcoin::secp256k1::{KeyPair, Message, Secp256k1, SecretKey, XOnlyPublicKey, self};
-       use bitcoin::address::{Address, Payload, WitnessProgram, WitnessVersion};
+       use bitcoin::network::Network;
+       use bitcoin::secp256k1::{Keypair, Message, Secp256k1, SecretKey, XOnlyPublicKey, self};
+       use bitcoin::address::{Address, Payload};
        use bitcoin::key::TweakedPublicKey;
 
        use core::time::Duration;
@@ -1529,7 +1433,7 @@ mod tests {
                let payment_paths = payment_paths();
                let payment_hash = payment_hash();
                let now = now();
-               let unsigned_invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let unsigned_invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1545,8 +1449,8 @@ mod tests {
                assert_eq!(unsigned_invoice.payer_metadata(), &[1; 32]);
                assert_eq!(unsigned_invoice.offer_chains(), Some(vec![ChainHash::using_genesis_block(Network::Bitcoin)]));
                assert_eq!(unsigned_invoice.metadata(), None);
-               assert_eq!(unsigned_invoice.amount(), Some(&Amount::Bitcoin { amount_msats: 1000 }));
-               assert_eq!(unsigned_invoice.description(), PrintableString("foo"));
+               assert_eq!(unsigned_invoice.amount(), Some(Amount::Bitcoin { amount_msats: 1000 }));
+               assert_eq!(unsigned_invoice.description(), Some(PrintableString("")));
                assert_eq!(unsigned_invoice.offer_features(), Some(&OfferFeatures::empty()));
                assert_eq!(unsigned_invoice.absolute_expiry(), None);
                assert_eq!(unsigned_invoice.message_paths(), &[]);
@@ -1565,10 +1469,8 @@ mod tests {
                #[cfg(feature = "std")]
                assert!(!unsigned_invoice.is_expired());
                assert_eq!(unsigned_invoice.payment_hash(), payment_hash);
-               assert_eq!(unsigned_invoice.amount_msats(), 1000);
-               assert_eq!(unsigned_invoice.fallbacks(), vec![]);
+               assert!(unsigned_invoice.fallbacks().is_empty());
                assert_eq!(unsigned_invoice.invoice_features(), &Bolt12InvoiceFeatures::empty());
-               assert_eq!(unsigned_invoice.signing_pubkey(), recipient_pubkey());
 
                match UnsignedBolt12Invoice::try_from(buffer) {
                        Err(e) => panic!("error parsing unsigned invoice: {:?}", e),
@@ -1589,8 +1491,8 @@ mod tests {
                assert_eq!(invoice.payer_metadata(), &[1; 32]);
                assert_eq!(invoice.offer_chains(), Some(vec![ChainHash::using_genesis_block(Network::Bitcoin)]));
                assert_eq!(invoice.metadata(), None);
-               assert_eq!(invoice.amount(), Some(&Amount::Bitcoin { amount_msats: 1000 }));
-               assert_eq!(invoice.description(), PrintableString("foo"));
+               assert_eq!(invoice.amount(), Some(Amount::Bitcoin { amount_msats: 1000 }));
+               assert_eq!(invoice.description(), Some(PrintableString("")));
                assert_eq!(invoice.offer_features(), Some(&OfferFeatures::empty()));
                assert_eq!(invoice.absolute_expiry(), None);
                assert_eq!(invoice.message_paths(), &[]);
@@ -1609,15 +1511,13 @@ mod tests {
                #[cfg(feature = "std")]
                assert!(!invoice.is_expired());
                assert_eq!(invoice.payment_hash(), payment_hash);
-               assert_eq!(invoice.amount_msats(), 1000);
-               assert_eq!(invoice.fallbacks(), vec![]);
+               assert!(invoice.fallbacks().is_empty());
                assert_eq!(invoice.invoice_features(), &Bolt12InvoiceFeatures::empty());
-               assert_eq!(invoice.signing_pubkey(), recipient_pubkey());
 
                let message = TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &invoice.bytes);
                assert!(merkle::verify_signature(&invoice.signature, &message, recipient_pubkey()).is_ok());
 
-               let digest = Message::from_slice(&invoice.signable_hash()).unwrap();
+               let digest = Message::from_digest(invoice.signable_hash());
                let pubkey = recipient_pubkey().into();
                let secp_ctx = Secp256k1::verification_only();
                assert!(secp_ctx.verify_schnorr(&invoice.signature, &digest, &pubkey).is_ok());
@@ -1631,7 +1531,7 @@ mod tests {
                                        metadata: None,
                                        currency: None,
                                        amount: Some(1000),
-                                       description: Some(&String::from("foo")),
+                                       description: Some(&String::from("")),
                                        features: None,
                                        absolute_expiry: None,
                                        paths: None,
@@ -1673,7 +1573,7 @@ mod tests {
                let payment_paths = payment_paths();
                let payment_hash = payment_hash();
                let now = now();
-               let invoice = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap()
+               let invoice = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap()
                        .build().unwrap()
                        .respond_with_no_std(payment_paths.clone(), payment_hash, recipient_pubkey(), now)
                        .unwrap()
@@ -1688,7 +1588,7 @@ mod tests {
                assert_eq!(invoice.offer_chains(), None);
                assert_eq!(invoice.metadata(), None);
                assert_eq!(invoice.amount(), None);
-               assert_eq!(invoice.description(), PrintableString("foo"));
+               assert_eq!(invoice.description(), Some(PrintableString("")));
                assert_eq!(invoice.offer_features(), None);
                assert_eq!(invoice.absolute_expiry(), None);
                assert_eq!(invoice.message_paths(), &[]);
@@ -1707,10 +1607,8 @@ mod tests {
                #[cfg(feature = "std")]
                assert!(!invoice.is_expired());
                assert_eq!(invoice.payment_hash(), payment_hash);
-               assert_eq!(invoice.amount_msats(), 1000);
-               assert_eq!(invoice.fallbacks(), vec![]);
+               assert!(invoice.fallbacks().is_empty());
                assert_eq!(invoice.invoice_features(), &Bolt12InvoiceFeatures::empty());
-               assert_eq!(invoice.signing_pubkey(), recipient_pubkey());
 
                let message = TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &invoice.bytes);
                assert!(merkle::verify_signature(&invoice.signature, &message, recipient_pubkey()).is_ok());
@@ -1724,7 +1622,7 @@ mod tests {
                                        metadata: None,
                                        currency: None,
                                        amount: None,
-                                       description: Some(&String::from("foo")),
+                                       description: Some(&String::from("")),
                                        features: None,
                                        absolute_expiry: None,
                                        paths: None,
@@ -1767,7 +1665,7 @@ mod tests {
                let future_expiry = Duration::from_secs(u64::max_value());
                let past_expiry = Duration::from_secs(0);
 
-               if let Err(e) = OfferBuilder::new("foo".into(), recipient_pubkey())
+               if let Err(e) = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .absolute_expiry(future_expiry)
                        .build().unwrap()
@@ -1781,7 +1679,7 @@ mod tests {
                        panic!("error building invoice: {:?}", e);
                }
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .absolute_expiry(past_expiry)
                        .build().unwrap()
@@ -1803,7 +1701,7 @@ mod tests {
                let future_expiry = Duration::from_secs(u64::max_value());
                let past_expiry = Duration::from_secs(0);
 
-               if let Err(e) = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap()
+               if let Err(e) = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap()
                        .absolute_expiry(future_expiry)
                        .build().unwrap()
                        .respond_with(payment_paths(), payment_hash(), recipient_pubkey())
@@ -1813,7 +1711,7 @@ mod tests {
                        panic!("error building invoice: {:?}", e);
                }
 
-               match RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap()
+               match RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap()
                        .absolute_expiry(past_expiry)
                        .build().unwrap()
                        .respond_with(payment_paths(), payment_hash(), recipient_pubkey())
@@ -1827,7 +1725,6 @@ mod tests {
 
        #[test]
        fn builds_invoice_from_offer_using_derived_keys() {
-               let desc = "foo".to_string();
                let node_id = recipient_pubkey();
                let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
                let entropy = FixedEntropy {};
@@ -1845,7 +1742,7 @@ mod tests {
                #[cfg(c_bindings)]
                use crate::offers::offer::OfferWithDerivedMetadataBuilder as OfferBuilder;
                let offer = OfferBuilder
-                       ::deriving_signing_pubkey(desc, node_id, &expanded_key, &entropy, &secp_ctx)
+                       ::deriving_signing_pubkey(node_id, &expanded_key, &entropy, &secp_ctx)
                        .amount_msats(1000)
                        .path(blinded_path)
                        .build().unwrap();
@@ -1864,9 +1761,8 @@ mod tests {
                let expanded_key = ExpandedKey::new(&KeyMaterial([41; 32]));
                assert!(invoice_request.verify(&expanded_key, &secp_ctx).is_err());
 
-               let desc = "foo".to_string();
                let offer = OfferBuilder
-                       ::deriving_signing_pubkey(desc, node_id, &expanded_key, &entropy, &secp_ctx)
+                       ::deriving_signing_pubkey(node_id, &expanded_key, &entropy, &secp_ctx)
                        .amount_msats(1000)
                        // Omit the path so that node_id is used for the signing pubkey instead of deriving
                        .build().unwrap();
@@ -1889,7 +1785,7 @@ mod tests {
                let entropy = FixedEntropy {};
                let secp_ctx = Secp256k1::new();
 
-               let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap()
+               let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap()
                        .build().unwrap();
 
                if let Err(e) = refund
@@ -1908,7 +1804,7 @@ mod tests {
                let now = now();
                let one_hour = Duration::from_secs(3600);
 
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1924,7 +1820,7 @@ mod tests {
                assert_eq!(invoice.relative_expiry(), one_hour);
                assert_eq!(tlv_stream.relative_expiry, Some(one_hour.as_secs() as u32));
 
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1943,7 +1839,7 @@ mod tests {
 
        #[test]
        fn builds_invoice_with_amount_from_request() {
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1960,7 +1856,7 @@ mod tests {
 
        #[test]
        fn builds_invoice_with_quantity_from_request() {
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Unbounded)
                        .build().unwrap()
@@ -1975,7 +1871,7 @@ mod tests {
                assert_eq!(invoice.amount_msats(), 2000);
                assert_eq!(tlv_stream.amount, Some(2000));
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Unbounded)
                        .build().unwrap()
@@ -1997,7 +1893,7 @@ mod tests {
                let x_only_pubkey = XOnlyPublicKey::from_keypair(&recipient_keys()).0;
                let tweaked_pubkey = TweakedPublicKey::dangerous_assume_tweaked(x_only_pubkey);
 
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2042,7 +1938,7 @@ mod tests {
                let mut features = Bolt12InvoiceFeatures::empty();
                features.set_basic_mpp_optional();
 
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2059,7 +1955,7 @@ mod tests {
 
        #[test]
        fn fails_signing_invoice() {
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2073,7 +1969,7 @@ mod tests {
                        Err(e) => assert_eq!(e, SignError::Signing),
                }
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2090,7 +1986,7 @@ mod tests {
 
        #[test]
        fn parses_invoice_with_payment_paths() {
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2145,7 +2041,7 @@ mod tests {
 
        #[test]
        fn parses_invoice_with_created_at() {
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2175,7 +2071,7 @@ mod tests {
 
        #[test]
        fn parses_invoice_with_relative_expiry() {
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2197,7 +2093,7 @@ mod tests {
 
        #[test]
        fn parses_invoice_with_payment_hash() {
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2227,7 +2123,7 @@ mod tests {
 
        #[test]
        fn parses_invoice_with_amount() {
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2255,7 +2151,7 @@ mod tests {
 
        #[test]
        fn parses_invoice_with_allow_mpp() {
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2286,7 +2182,7 @@ mod tests {
                let x_only_pubkey = XOnlyPublicKey::from_keypair(&recipient_keys()).0;
                let tweaked_pubkey = TweakedPublicKey::dangerous_assume_tweaked(x_only_pubkey);
 
-               let offer = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let offer = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap();
                let invoice_request = offer
@@ -2341,7 +2237,7 @@ mod tests {
 
        #[test]
        fn parses_invoice_with_node_id() {
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2403,11 +2299,11 @@ mod tests {
 
                let blinded_node_id_sign = |message: &UnsignedBolt12Invoice| {
                        let secp_ctx = Secp256k1::new();
-                       let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[46; 32]).unwrap());
+                       let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[46; 32]).unwrap());
                        Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
                };
 
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .clear_signing_pubkey()
                        .amount_msats(1000)
                        .path(paths[0].clone())
@@ -2429,7 +2325,7 @@ mod tests {
                        panic!("error parsing invoice: {:?}", e);
                }
 
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .clear_signing_pubkey()
                        .amount_msats(1000)
                        .path(paths[0].clone())
@@ -2458,7 +2354,7 @@ mod tests {
        #[test]
        fn fails_parsing_invoice_without_signature() {
                let mut buffer = Vec::new();
-               OfferBuilder::new("foo".into(), recipient_pubkey())
+               OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2477,7 +2373,7 @@ mod tests {
 
        #[test]
        fn fails_parsing_invoice_with_invalid_signature() {
-               let mut invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let mut invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2502,7 +2398,7 @@ mod tests {
 
        #[test]
        fn fails_parsing_invoice_with_extra_tlv_records() {
-               let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()