Merge pull request #2957 from G8XSU/pause-events
[rust-lightning] / lightning / src / offers / invoice_request.rs
index 357b85c5cf07b89a06cb591278e6e61ed8ac4245..faeef26c82f2332b31f6c689e18cd49889cae2af 100644 (file)
@@ -65,7 +65,7 @@ use core::ops::Deref;
 use crate::sign::EntropySource;
 use crate::io;
 use crate::blinded_path::BlindedPath;
-use crate::ln::PaymentHash;
+use crate::ln::types::PaymentHash;
 use crate::ln::channelmanager::PaymentId;
 use crate::ln::features::InvoiceRequestFeatures;
 use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce};
@@ -747,7 +747,27 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { (
                        return Err(Bolt12SemanticError::UnknownRequiredFeatures);
                }
 
-               <$builder>::for_offer(&$contents, payment_paths, created_at, payment_hash)
+               let signing_pubkey = match $contents.contents.inner.offer.signing_pubkey() {
+                       Some(signing_pubkey) => signing_pubkey,
+                       None => return Err(Bolt12SemanticError::MissingSigningPubkey),
+               };
+
+               <$builder>::for_offer(&$contents, payment_paths, created_at, payment_hash, signing_pubkey)
+       }
+
+       #[cfg(test)]
+       #[allow(dead_code)]
+       pub(super) fn respond_with_no_std_using_signing_pubkey(
+               &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
+               created_at: core::time::Duration, signing_pubkey: PublicKey
+       ) -> Result<$builder, Bolt12SemanticError> {
+               debug_assert!($contents.contents.inner.offer.signing_pubkey().is_none());
+
+               if $contents.invoice_request_features().requires_unknown_bits() {
+                       return Err(Bolt12SemanticError::UnknownRequiredFeatures);
+               }
+
+               <$builder>::for_offer(&$contents, payment_paths, created_at, payment_hash, signing_pubkey)
        }
 } }
 
@@ -855,6 +875,11 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
                        Some(keys) => keys,
                };
 
+               match $contents.contents.inner.offer.signing_pubkey() {
+                       Some(signing_pubkey) => debug_assert_eq!(signing_pubkey, keys.public_key()),
+                       None => return Err(Bolt12SemanticError::MissingSigningPubkey),
+               }
+
                <$builder>::for_offer_using_keys(
                        &$self.inner, payment_paths, created_at, payment_hash, keys
                )
@@ -959,6 +984,7 @@ impl InvoiceRequestContentsWithoutPayerId {
                        quantity: self.quantity,
                        payer_id: None,
                        payer_note: self.payer_note.as_ref(),
+                       paths: None,
                };
 
                (payer, offer, invoice_request)
@@ -991,6 +1017,8 @@ pub(super) const INVOICE_REQUEST_TYPES: core::ops::Range<u64> = 80..160;
 /// [`Refund::payer_id`]: crate::offers::refund::Refund::payer_id
 pub(super) const INVOICE_REQUEST_PAYER_ID_TYPE: u64 = 88;
 
+// This TLV stream is used for both InvoiceRequest and Refund, but not all TLV records are valid for
+// InvoiceRequest as noted below.
 tlv_stream!(InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef, INVOICE_REQUEST_TYPES, {
        (80, chain: ChainHash),
        (82, amount: (u64, HighZeroBytesDroppedBigSize)),
@@ -998,6 +1026,8 @@ tlv_stream!(InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef, INVOICE_REQUEST
        (86, quantity: (u64, HighZeroBytesDroppedBigSize)),
        (INVOICE_REQUEST_PAYER_ID_TYPE, payer_id: PublicKey),
        (89, payer_note: (String, WithoutLength)),
+       // Only used for Refund since the onion message of an InvoiceRequest has a reply path.
+       (90, paths: (Vec<BlindedPath>, WithoutLength)),
 });
 
 type FullInvoiceRequestTlvStream =
@@ -1080,7 +1110,9 @@ impl TryFrom<PartialInvoiceRequestTlvStream> for InvoiceRequestContents {
                let (
                        PayerTlvStream { metadata },
                        offer_tlv_stream,
-                       InvoiceRequestTlvStream { chain, amount, features, quantity, payer_id, payer_note },
+                       InvoiceRequestTlvStream {
+                               chain, amount, features, quantity, payer_id, payer_note, paths,
+                       },
                ) = tlv_stream;
 
                let payer = match metadata {
@@ -1107,6 +1139,10 @@ impl TryFrom<PartialInvoiceRequestTlvStream> for InvoiceRequestContents {
                        Some(payer_id) => payer_id,
                };
 
+               if paths.is_some() {
+                       return Err(Bolt12SemanticError::UnexpectedPaths);
+               }
+
                Ok(InvoiceRequestContents {
                        inner: InvoiceRequestContentsWithoutPayerId {
                                payer, offer, chain, amount_msats: amount, features, quantity, payer_note,
@@ -1196,7 +1232,7 @@ mod tests {
 
        #[test]
        fn builds_invoice_request_with_defaults() {
-               let unsigned_invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let unsigned_invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1212,13 +1248,13 @@ mod tests {
                assert_eq!(unsigned_invoice_request.chains(), vec![ChainHash::using_genesis_block(Network::Bitcoin)]);
                assert_eq!(unsigned_invoice_request.metadata(), None);
                assert_eq!(unsigned_invoice_request.amount(), Some(&Amount::Bitcoin { amount_msats: 1000 }));
-               assert_eq!(unsigned_invoice_request.description(), PrintableString("foo"));
+               assert_eq!(unsigned_invoice_request.description(), Some(PrintableString("")));
                assert_eq!(unsigned_invoice_request.offer_features(), &OfferFeatures::empty());
                assert_eq!(unsigned_invoice_request.absolute_expiry(), None);
                assert_eq!(unsigned_invoice_request.paths(), &[]);
                assert_eq!(unsigned_invoice_request.issuer(), None);
                assert_eq!(unsigned_invoice_request.supported_quantity(), Quantity::One);
-               assert_eq!(unsigned_invoice_request.signing_pubkey(), recipient_pubkey());
+               assert_eq!(unsigned_invoice_request.signing_pubkey(), Some(recipient_pubkey()));
                assert_eq!(unsigned_invoice_request.chain(), ChainHash::using_genesis_block(Network::Bitcoin));
                assert_eq!(unsigned_invoice_request.amount_msats(), None);
                assert_eq!(unsigned_invoice_request.invoice_request_features(), &InvoiceRequestFeatures::empty());
@@ -1244,13 +1280,13 @@ mod tests {
                assert_eq!(invoice_request.chains(), vec![ChainHash::using_genesis_block(Network::Bitcoin)]);
                assert_eq!(invoice_request.metadata(), None);
                assert_eq!(invoice_request.amount(), Some(&Amount::Bitcoin { amount_msats: 1000 }));
-               assert_eq!(invoice_request.description(), PrintableString("foo"));
+               assert_eq!(invoice_request.description(), Some(PrintableString("")));
                assert_eq!(invoice_request.offer_features(), &OfferFeatures::empty());
                assert_eq!(invoice_request.absolute_expiry(), None);
                assert_eq!(invoice_request.paths(), &[]);
                assert_eq!(invoice_request.issuer(), None);
                assert_eq!(invoice_request.supported_quantity(), Quantity::One);
-               assert_eq!(invoice_request.signing_pubkey(), recipient_pubkey());
+               assert_eq!(invoice_request.signing_pubkey(), Some(recipient_pubkey()));
                assert_eq!(invoice_request.chain(), ChainHash::using_genesis_block(Network::Bitcoin));
                assert_eq!(invoice_request.amount_msats(), None);
                assert_eq!(invoice_request.invoice_request_features(), &InvoiceRequestFeatures::empty());
@@ -1270,7 +1306,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,
@@ -1285,6 +1321,7 @@ mod tests {
                                        quantity: None,
                                        payer_id: Some(&payer_pubkey()),
                                        payer_note: None,
+                                       paths: None,
                                },
                                SignatureTlvStreamRef { signature: Some(&invoice_request.signature()) },
                        ),
@@ -1301,7 +1338,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()
@@ -1311,7 +1348,7 @@ mod tests {
                        panic!("error building invoice_request: {:?}", e);
                }
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .absolute_expiry(past_expiry)
                        .build().unwrap()
@@ -1331,7 +1368,7 @@ mod tests {
                let secp_ctx = Secp256k1::new();
                let payment_id = PaymentId([1; 32]);
 
-               let offer = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let offer = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap();
                let invoice_request = offer
@@ -1404,7 +1441,7 @@ mod tests {
                let secp_ctx = Secp256k1::new();
                let payment_id = PaymentId([1; 32]);
 
-               let offer = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let offer = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap();
                let invoice_request = offer
@@ -1474,7 +1511,7 @@ mod tests {
                let mainnet = ChainHash::using_genesis_block(Network::Bitcoin);
                let testnet = ChainHash::using_genesis_block(Network::Testnet);
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1485,7 +1522,7 @@ mod tests {
                assert_eq!(invoice_request.chain(), mainnet);
                assert_eq!(tlv_stream.chain, None);
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .chain(Network::Testnet)
                        .build().unwrap()
@@ -1497,7 +1534,7 @@ mod tests {
                assert_eq!(invoice_request.chain(), testnet);
                assert_eq!(tlv_stream.chain, Some(&testnet));
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .chain(Network::Bitcoin)
                        .chain(Network::Testnet)
@@ -1510,7 +1547,7 @@ mod tests {
                assert_eq!(invoice_request.chain(), mainnet);
                assert_eq!(tlv_stream.chain, None);
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .chain(Network::Bitcoin)
                        .chain(Network::Testnet)
@@ -1524,7 +1561,7 @@ mod tests {
                assert_eq!(invoice_request.chain(), testnet);
                assert_eq!(tlv_stream.chain, Some(&testnet));
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .chain(Network::Testnet)
                        .build().unwrap()
@@ -1535,7 +1572,7 @@ mod tests {
                        Err(e) => assert_eq!(e, Bolt12SemanticError::UnsupportedChain),
                }
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .chain(Network::Testnet)
                        .build().unwrap()
@@ -1549,7 +1586,7 @@ mod tests {
 
        #[test]
        fn builds_invoice_request_with_amount() {
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1560,7 +1597,7 @@ mod tests {
                assert_eq!(invoice_request.amount_msats(), Some(1000));
                assert_eq!(tlv_stream.amount, Some(1000));
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1572,7 +1609,7 @@ mod tests {
                assert_eq!(invoice_request.amount_msats(), Some(1000));
                assert_eq!(tlv_stream.amount, Some(1000));
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1583,7 +1620,7 @@ mod tests {
                assert_eq!(invoice_request.amount_msats(), Some(1001));
                assert_eq!(tlv_stream.amount, Some(1001));
 
-               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()
@@ -1593,7 +1630,7 @@ mod tests {
                        Err(e) => assert_eq!(e, Bolt12SemanticError::InsufficientAmount),
                }
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Unbounded)
                        .build().unwrap()
@@ -1605,7 +1642,7 @@ mod tests {
                        Err(e) => assert_eq!(e, Bolt12SemanticError::InsufficientAmount),
                }
 
-               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()
@@ -1615,7 +1652,7 @@ mod tests {
                        Err(e) => assert_eq!(e, Bolt12SemanticError::InvalidAmount),
                }
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Unbounded)
                        .build().unwrap()
@@ -1628,7 +1665,7 @@ mod tests {
                        Err(e) => assert_eq!(e, Bolt12SemanticError::InsufficientAmount),
                }
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build()
@@ -1637,7 +1674,7 @@ mod tests {
                        Err(e) => assert_eq!(e, Bolt12SemanticError::MissingAmount),
                }
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Unbounded)
                        .build().unwrap()
@@ -1652,7 +1689,7 @@ mod tests {
 
        #[test]
        fn builds_invoice_request_with_features() {
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1663,7 +1700,7 @@ mod tests {
                assert_eq!(invoice_request.invoice_request_features(), &InvoiceRequestFeatures::unknown());
                assert_eq!(tlv_stream.features, Some(&InvoiceRequestFeatures::unknown()));
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1681,7 +1718,7 @@ mod tests {
                let one = NonZeroU64::new(1).unwrap();
                let ten = NonZeroU64::new(10).unwrap();
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::One)
                        .build().unwrap()
@@ -1692,7 +1729,7 @@ mod tests {
                assert_eq!(invoice_request.quantity(), None);
                assert_eq!(tlv_stream.quantity, None);
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::One)
                        .build().unwrap()
@@ -1704,7 +1741,7 @@ mod tests {
                        Err(e) => assert_eq!(e, Bolt12SemanticError::UnexpectedQuantity),
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Bounded(ten))
                        .build().unwrap()
@@ -1717,7 +1754,7 @@ mod tests {
                assert_eq!(invoice_request.amount_msats(), Some(10_000));
                assert_eq!(tlv_stream.amount, Some(10_000));
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Bounded(ten))
                        .build().unwrap()
@@ -1729,7 +1766,7 @@ mod tests {
                        Err(e) => assert_eq!(e, Bolt12SemanticError::InvalidQuantity),
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Unbounded)
                        .build().unwrap()
@@ -1742,7 +1779,7 @@ mod tests {
                assert_eq!(invoice_request.amount_msats(), Some(2_000));
                assert_eq!(tlv_stream.amount, Some(2_000));
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Unbounded)
                        .build().unwrap()
@@ -1753,7 +1790,7 @@ mod tests {
                        Err(e) => assert_eq!(e, Bolt12SemanticError::MissingQuantity),
                }
 
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Bounded(one))
                        .build().unwrap()
@@ -1767,7 +1804,7 @@ mod tests {
 
        #[test]
        fn builds_invoice_request_with_payer_note() {
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1778,7 +1815,7 @@ mod tests {
                assert_eq!(invoice_request.payer_note(), Some(PrintableString("bar")));
                assert_eq!(tlv_stream.payer_note, Some(&String::from("bar")));
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1793,7 +1830,7 @@ mod tests {
 
        #[test]
        fn fails_signing_invoice_request() {
-               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()
@@ -1804,7 +1841,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()
@@ -1818,7 +1855,7 @@ mod tests {
 
        #[test]
        fn fails_responding_with_unknown_required_features() {
-               match OfferBuilder::new("foo".into(), recipient_pubkey())
+               match OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![42; 32], payer_pubkey()).unwrap()
@@ -1834,7 +1871,7 @@ mod tests {
 
        #[test]
        fn parses_invoice_request_with_metadata() {
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1851,7 +1888,7 @@ mod tests {
 
        #[test]
        fn parses_invoice_request_with_chain() {
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1866,7 +1903,7 @@ mod tests {
                        panic!("error parsing invoice_request: {:?}", e);
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1885,7 +1922,7 @@ mod tests {
 
        #[test]
        fn parses_invoice_request_with_amount() {
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1899,7 +1936,7 @@ mod tests {
                        panic!("error parsing invoice_request: {:?}", e);
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .amount_msats(1000).unwrap()
@@ -1913,7 +1950,7 @@ mod tests {
                        panic!("error parsing invoice_request: {:?}", e);
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .build_unchecked()
@@ -1927,7 +1964,7 @@ mod tests {
                        Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount)),
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1943,7 +1980,8 @@ mod tests {
                        Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InsufficientAmount)),
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
+                       .description("foo".to_string())
                        .amount(Amount::Currency { iso4217_code: *b"USD", amount: 1000 })
                        .build_unchecked()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -1960,7 +1998,7 @@ mod tests {
                        },
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Unbounded)
                        .build().unwrap()
@@ -1983,7 +2021,7 @@ mod tests {
                let one = NonZeroU64::new(1).unwrap();
                let ten = NonZeroU64::new(10).unwrap();
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::One)
                        .build().unwrap()
@@ -1998,7 +2036,7 @@ mod tests {
                        panic!("error parsing invoice_request: {:?}", e);
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::One)
                        .build().unwrap()
@@ -2018,7 +2056,7 @@ mod tests {
                        },
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Bounded(ten))
                        .build().unwrap()
@@ -2035,7 +2073,7 @@ mod tests {
                        panic!("error parsing invoice_request: {:?}", e);
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Bounded(ten))
                        .build().unwrap()
@@ -2053,7 +2091,7 @@ mod tests {
                        Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidQuantity)),
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Unbounded)
                        .build().unwrap()
@@ -2070,7 +2108,7 @@ mod tests {
                        panic!("error parsing invoice_request: {:?}", e);
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Unbounded)
                        .build().unwrap()
@@ -2086,7 +2124,7 @@ mod tests {
                        Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingQuantity)),
                }
 
-               let invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Bounded(one))
                        .build().unwrap()
@@ -2105,7 +2143,7 @@ mod tests {
 
        #[test]
        fn fails_parsing_invoice_request_without_metadata() {
-               let offer = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let offer = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap();
                let unsigned_invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2126,7 +2164,7 @@ mod tests {
 
        #[test]
        fn fails_parsing_invoice_request_without_payer_id() {
-               let offer = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let offer = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap();
                let unsigned_invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2145,7 +2183,7 @@ mod tests {
 
        #[test]
        fn fails_parsing_invoice_request_without_node_id() {
-               let offer = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let offer = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap();
                let unsigned_invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2167,7 +2205,7 @@ mod tests {
        #[test]
        fn fails_parsing_invoice_request_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()
@@ -2183,7 +2221,7 @@ mod tests {
 
        #[test]
        fn fails_parsing_invoice_request_with_invalid_signature() {
-               let mut invoice_request = OfferBuilder::new("foo".into(), recipient_pubkey())
+               let mut invoice_request = OfferBuilder::new(recipient_pubkey())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], payer_pubkey()).unwrap()
@@ -2207,7 +2245,7 @@ mod tests {
        fn fails_parsing_invoice_request_with_extra_tlv_records() {
                let secp_ctx = Secp256k1::new();
                let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
-               let invoice_request = OfferBuilder::new("foo".into(), keys.public_key())
+               let invoice_request = OfferBuilder::new(keys.public_key())
                        .amount_msats(1000)
                        .build().unwrap()
                        .request_invoice(vec![1; 32], keys.public_key()).unwrap()
@@ -2231,7 +2269,6 @@ mod tests {
 
        #[test]
        fn copies_verified_invoice_request_fields() {
-               let desc = "foo".to_string();
                let node_id = recipient_pubkey();
                let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
                let entropy = FixedEntropy {};
@@ -2240,12 +2277,12 @@ 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)
                        .chain(Network::Testnet)
                        .amount_msats(1000)
                        .supported_quantity(Quantity::Unbounded)
                        .build().unwrap();
-               assert_eq!(offer.signing_pubkey(), node_id);
+               assert_eq!(offer.signing_pubkey(), Some(node_id));
 
                let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
                        .chain(Network::Testnet).unwrap()