From df58f26ada98975c0ec4c6ffdb496255d1c7827c Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Thu, 1 Aug 2024 10:56:51 -0500 Subject: [PATCH] Rename Offer::signing_pubkey to Offer::issuer_signing_pubkey The spec was recently changed to use offer_issuer_id instead of offer_node_id. LDK always used signing_pubkey to avoid confusion with a node_id. Rename it to issuer_signing_pubkey now as InvoiceRequest and Bolt12Invoice will have similarly named methods in upcoming commits. --- lightning/src/ln/channelmanager.rs | 8 +-- lightning/src/ln/offers_tests.rs | 22 +++---- lightning/src/offers/invoice.rs | 18 +++--- lightning/src/offers/invoice_request.rs | 26 ++++---- lightning/src/offers/nonce.rs | 4 +- lightning/src/offers/offer.rs | 84 ++++++++++++------------- lightning/src/offers/parse.rs | 14 +++-- lightning/src/offers/refund.rs | 16 ++--- lightning/src/offers/static_invoice.rs | 41 ++++++------ 9 files changed, 120 insertions(+), 113 deletions(-) diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 03164e04f..33a56a4f9 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -9197,7 +9197,7 @@ where /// # Limitations /// /// Requires a direct connection to an introduction node in [`Offer::paths`] or to - /// [`Offer::signing_pubkey`], if empty. A similar restriction applies to the responding + /// [`Offer::issuer_signing_pubkey`], if empty. A similar restriction applies to the responding /// [`Bolt12Invoice::payment_paths`]. /// /// # Errors @@ -9288,10 +9288,10 @@ where let message = OffersMessage::InvoiceRequest(invoice_request.clone()); pending_offers_messages.push((message, instructions)); }); - } else if let Some(signing_pubkey) = invoice_request.signing_pubkey() { + } else if let Some(node_id) = invoice_request.issuer_signing_pubkey() { for reply_path in reply_paths { let instructions = MessageSendInstructions::WithSpecifiedReplyPath { - destination: Destination::Node(signing_pubkey), + destination: Destination::Node(node_id), reply_path, }; let message = OffersMessage::InvoiceRequest(invoice_request.clone()); @@ -9299,7 +9299,7 @@ where } } else { debug_assert!(false); - return Err(Bolt12SemanticError::MissingSigningPubkey); + return Err(Bolt12SemanticError::MissingIssuerSigningPubkey); } Ok(()) diff --git a/lightning/src/ln/offers_tests.rs b/lightning/src/ln/offers_tests.rs index 3b9317e46..a8124aab2 100644 --- a/lightning/src/ln/offers_tests.rs +++ b/lightning/src/ln/offers_tests.rs @@ -305,7 +305,7 @@ fn prefers_non_tor_nodes_in_blinded_paths() { .create_offer_builder(None).unwrap() .amount_msats(10_000_000) .build().unwrap(); - assert_ne!(offer.signing_pubkey(), Some(bob_id)); + assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { let introduction_node_id = resolve_introduction_node(david, &path); @@ -321,7 +321,7 @@ fn prefers_non_tor_nodes_in_blinded_paths() { .create_offer_builder(None).unwrap() .amount_msats(10_000_000) .build().unwrap(); - assert_ne!(offer.signing_pubkey(), Some(bob_id)); + assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { let introduction_node_id = resolve_introduction_node(david, &path); @@ -372,7 +372,7 @@ fn prefers_more_connected_nodes_in_blinded_paths() { .create_offer_builder(None).unwrap() .amount_msats(10_000_000) .build().unwrap(); - assert_ne!(offer.signing_pubkey(), Some(bob_id)); + assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { let introduction_node_id = resolve_introduction_node(david, &path); @@ -541,7 +541,7 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() { .unwrap() .amount_msats(10_000_000) .build().unwrap(); - assert_ne!(offer.signing_pubkey(), Some(alice_id)); + assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id)); @@ -709,7 +709,7 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() { .create_offer_builder(None).unwrap() .amount_msats(10_000_000) .build().unwrap(); - assert_ne!(offer.signing_pubkey(), Some(alice_id)); + assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id)); @@ -832,7 +832,7 @@ fn pays_for_offer_without_blinded_paths() { .clear_paths() .amount_msats(10_000_000) .build().unwrap(); - assert_eq!(offer.signing_pubkey(), Some(alice_id)); + assert_eq!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(offer.paths().is_empty()); let payment_id = PaymentId([1; 32]); @@ -955,7 +955,7 @@ fn send_invoice_requests_with_distinct_reply_path() { .unwrap() .amount_msats(10_000_000) .build().unwrap(); - assert_ne!(offer.signing_pubkey(), Some(alice_id)); + assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id)); @@ -1090,7 +1090,7 @@ fn creates_and_pays_for_offer_with_retry() { .create_offer_builder(None).unwrap() .amount_msats(10_000_000) .build().unwrap(); - assert_ne!(offer.signing_pubkey(), Some(alice_id)); + assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id)); @@ -1248,7 +1248,7 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() { .create_offer_builder(None).unwrap() .amount_msats(10_000_000) .build().unwrap(); - assert_ne!(offer.signing_pubkey(), Some(alice_id)); + assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id)); @@ -1379,7 +1379,7 @@ fn fails_authentication_when_handling_invoice_request() { .amount_msats(10_000_000) .build().unwrap(); assert_eq!(offer.metadata(), None); - assert_ne!(offer.signing_pubkey(), Some(alice_id)); + assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id)); @@ -1490,7 +1490,7 @@ fn fails_authentication_when_handling_invoice_for_offer() { .unwrap() .amount_msats(10_000_000) .build().unwrap(); - assert_ne!(offer.signing_pubkey(), Some(alice_id)); + assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id)); assert!(!offer.paths().is_empty()); for path in offer.paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id)); diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index 865939b07..144ed4ef0 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -1335,7 +1335,7 @@ impl TryFrom for InvoiceContents { check_invoice_signing_pubkey(&fields.signing_pubkey, &offer_tlv_stream)?; - if offer_tlv_stream.node_id.is_none() && offer_tlv_stream.paths.is_none() { + if offer_tlv_stream.issuer_id.is_none() && offer_tlv_stream.paths.is_none() { let refund = RefundContents::try_from( (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) )?; @@ -1373,9 +1373,9 @@ pub(super) fn construct_payment_paths( pub(super) fn check_invoice_signing_pubkey( invoice_signing_pubkey: &PublicKey, offer_tlv_stream: &OfferTlvStream ) -> Result<(), Bolt12SemanticError> { - match (&offer_tlv_stream.node_id, &offer_tlv_stream.paths) { - (Some(expected_signing_pubkey), _) => { - if invoice_signing_pubkey != expected_signing_pubkey { + match (&offer_tlv_stream.issuer_id, &offer_tlv_stream.paths) { + (Some(issuer_signing_pubkey), _) => { + if invoice_signing_pubkey != issuer_signing_pubkey { return Err(Bolt12SemanticError::InvalidSigningPubkey); } }, @@ -1561,7 +1561,7 @@ mod tests { paths: None, issuer: None, quantity_max: None, - node_id: Some(&recipient_pubkey()), + issuer_id: Some(&recipient_pubkey()), }, InvoiceRequestTlvStreamRef { chain: None, @@ -1654,7 +1654,7 @@ mod tests { paths: None, issuer: None, quantity_max: None, - node_id: None, + issuer_id: None, }, InvoiceRequestTlvStreamRef { chain: None, @@ -1791,7 +1791,7 @@ mod tests { let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx) .amount_msats(1000) - // Omit the path so that node_id is used for the signing pubkey instead of deriving + // Omit the path so that node_id is used for the signing pubkey instead of deriving it .build().unwrap(); let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap() .build().unwrap() @@ -2359,7 +2359,7 @@ mod tests { }; let invoice = OfferBuilder::new(recipient_pubkey()) - .clear_signing_pubkey() + .clear_issuer_signing_pubkey() .amount_msats(1000) .path(paths[0].clone()) .path(paths[1].clone()) @@ -2381,7 +2381,7 @@ mod tests { } let invoice = OfferBuilder::new(recipient_pubkey()) - .clear_signing_pubkey() + .clear_issuer_signing_pubkey() .amount_msats(1000) .path(paths[0].clone()) .path(paths[1].clone()) diff --git a/lightning/src/offers/invoice_request.rs b/lightning/src/offers/invoice_request.rs index dc2fd4bf1..6c48fbc6e 100644 --- a/lightning/src/offers/invoice_request.rs +++ b/lightning/src/offers/invoice_request.rs @@ -728,7 +728,7 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { ( /// The `payment_paths` parameter is useful for maintaining the payment recipient's privacy. It /// must contain one or more elements ordered from most-preferred to least-preferred, if there's /// a preference. Note, however, that any privacy is lost if a public node id was used for - /// [`Offer::signing_pubkey`]. + /// [`Offer::issuer_signing_pubkey`]. /// /// Errors if the request contains unknown required features. /// @@ -749,9 +749,9 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { ( return Err(Bolt12SemanticError::UnknownRequiredFeatures); } - let signing_pubkey = match $contents.contents.inner.offer.signing_pubkey() { + let signing_pubkey = match $contents.contents.inner.offer.issuer_signing_pubkey() { Some(signing_pubkey) => signing_pubkey, - None => return Err(Bolt12SemanticError::MissingSigningPubkey), + None => return Err(Bolt12SemanticError::MissingIssuerSigningPubkey), }; <$builder>::for_offer(&$contents, payment_paths, created_at, payment_hash, signing_pubkey) @@ -763,7 +763,7 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { ( &$self, payment_paths: Vec, payment_hash: PaymentHash, created_at: core::time::Duration, signing_pubkey: PublicKey ) -> Result<$builder, Bolt12SemanticError> { - debug_assert!($contents.contents.inner.offer.signing_pubkey().is_none()); + debug_assert!($contents.contents.inner.offer.issuer_signing_pubkey().is_none()); if $contents.invoice_request_features().requires_unknown_bits() { return Err(Bolt12SemanticError::UnknownRequiredFeatures); @@ -914,9 +914,9 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { ( Some(keys) => keys, }; - match $contents.contents.inner.offer.signing_pubkey() { + match $contents.contents.inner.offer.issuer_signing_pubkey() { Some(signing_pubkey) => debug_assert_eq!(signing_pubkey, keys.public_key()), - None => return Err(Bolt12SemanticError::MissingSigningPubkey), + None => return Err(Bolt12SemanticError::MissingIssuerSigningPubkey), } <$builder>::for_offer_using_keys( @@ -1297,7 +1297,7 @@ mod tests { 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(), Some(recipient_pubkey())); + assert_eq!(unsigned_invoice_request.issuer_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()); @@ -1329,7 +1329,7 @@ mod tests { 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(), Some(recipient_pubkey())); + assert_eq!(invoice_request.issuer_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()); @@ -1355,7 +1355,7 @@ mod tests { paths: None, issuer: None, quantity_max: None, - node_id: Some(&recipient_pubkey()), + issuer_id: Some(&recipient_pubkey()), }, InvoiceRequestTlvStreamRef { chain: None, @@ -2234,14 +2234,14 @@ mod tests { } #[test] - fn fails_parsing_invoice_request_without_node_id() { + fn fails_parsing_invoice_request_without_issuer_id() { let offer = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .build().unwrap(); let unsigned_invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap() .build().unwrap(); let mut tlv_stream = unsigned_invoice_request.contents.as_tlv_stream(); - tlv_stream.1.node_id = None; + tlv_stream.1.issuer_id = None; let mut buffer = Vec::new(); tlv_stream.write(&mut buffer).unwrap(); @@ -2249,7 +2249,7 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey)); + assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingIssuerSigningPubkey)); }, } } @@ -2334,7 +2334,7 @@ mod tests { .amount_msats(1000) .supported_quantity(Quantity::Unbounded) .build().unwrap(); - assert_eq!(offer.signing_pubkey(), Some(node_id)); + assert_eq!(offer.issuer_signing_pubkey(), Some(node_id)); let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap() .chain(Network::Testnet).unwrap() diff --git a/lightning/src/offers/nonce.rs b/lightning/src/offers/nonce.rs index 1dd21e6c8..067541412 100644 --- a/lightning/src/offers/nonce.rs +++ b/lightning/src/offers/nonce.rs @@ -20,11 +20,11 @@ use crate::prelude::*; /// A 128-bit number used only once. /// -/// Needed when constructing [`Offer::metadata`] and deriving [`Offer::signing_pubkey`] from +/// Needed when constructing [`Offer::metadata`] and deriving [`Offer::issuer_signing_pubkey`] from /// [`ExpandedKey`]. Must not be reused for any other derivation without first hashing. /// /// [`Offer::metadata`]: crate::offers::offer::Offer::metadata -/// [`Offer::signing_pubkey`]: crate::offers::offer::Offer::signing_pubkey +/// [`Offer::issuer_signing_pubkey`]: crate::offers::offer::Offer::issuer_signing_pubkey /// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Nonce(pub(crate) [u8; Self::LENGTH]); diff --git a/lightning/src/offers/offer.rs b/lightning/src/offers/offer.rs index 27a79166b..2a1a68575 100644 --- a/lightning/src/offers/offer.rs +++ b/lightning/src/offers/offer.rs @@ -207,8 +207,8 @@ impl MetadataStrategy for DerivedMetadata {} macro_rules! offer_explicit_metadata_builder_methods { ( $self: ident, $self_type: ty, $return_type: ty, $return_value: expr ) => { - /// Creates a new builder for an offer using the [`Offer::signing_pubkey`] for signing invoices. - /// The associated secret key must be remembered while the offer is valid. + /// Creates a new builder for an offer using the `signing_pubkey` for signing invoices. The + /// associated secret key must be remembered while the offer is valid. /// /// Use a different pubkey per offer to avoid correlating offers. /// @@ -224,7 +224,7 @@ macro_rules! offer_explicit_metadata_builder_methods { ( offer: OfferContents { chains: None, metadata: None, amount: None, description: None, features: OfferFeatures::empty(), absolute_expiry: None, issuer: None, paths: None, - supported_quantity: Quantity::One, signing_pubkey: Some(signing_pubkey), + supported_quantity: Quantity::One, issuer_signing_pubkey: Some(signing_pubkey), }, metadata_strategy: core::marker::PhantomData, secp_ctx: None, @@ -244,7 +244,7 @@ macro_rules! offer_derived_metadata_builder_methods { ($secp_context: ty) => { /// Similar to [`OfferBuilder::new`] except, if [`OfferBuilder::path`] is called, the signing /// pubkey is derived from the given [`ExpandedKey`] and [`Nonce`]. This provides recipient /// privacy by using a different signing pubkey for each offer. Otherwise, the provided - /// `node_id` is used for the signing pubkey. + /// `node_id` is used for [`Offer::issuer_signing_pubkey`]. /// /// Also, sets the metadata when [`OfferBuilder::build`] is called such that it can be used by /// [`InvoiceRequest::verify_using_metadata`] to determine if the request was produced for the @@ -265,7 +265,7 @@ macro_rules! offer_derived_metadata_builder_methods { ($secp_context: ty) => { offer: OfferContents { chains: None, metadata: Some(metadata), amount: None, description: None, features: OfferFeatures::empty(), absolute_expiry: None, issuer: None, paths: None, - supported_quantity: Quantity::One, signing_pubkey: Some(node_id), + supported_quantity: Quantity::One, issuer_signing_pubkey: Some(node_id), }, metadata_strategy: core::marker::PhantomData, secp_ctx: Some(secp_ctx), @@ -342,7 +342,7 @@ macro_rules! offer_builder_methods { ( } /// Adds a blinded path to [`Offer::paths`]. Must include at least one path if only connected by - /// private channels or if [`Offer::signing_pubkey`] is not a public node id. + /// private channels or if [`Offer::issuer_signing_pubkey`] is not a public node id. /// /// Successive calls to this method will add another blinded path. Caller is responsible for not /// adding duplicate paths. @@ -403,7 +403,7 @@ macro_rules! offer_builder_methods { ( debug_assert_eq!(tlv_stream.metadata, None); tlv_stream.metadata = None; if metadata.derives_recipient_keys() { - tlv_stream.node_id = None; + tlv_stream.issuer_id = None; } // Either replace the signing pubkey with the derived pubkey or include the metadata @@ -412,7 +412,7 @@ macro_rules! offer_builder_methods { ( let (derived_metadata, keys) = metadata.derive_from(iv_bytes, tlv_stream, $self.secp_ctx); match keys { - Some(keys) => $self.offer.signing_pubkey = Some(keys.public_key()), + Some(keys) => $self.offer.issuer_signing_pubkey = Some(keys.public_key()), None => $self.offer.metadata = Some(derived_metadata), } } else { @@ -459,8 +459,8 @@ macro_rules! offer_builder_test_methods { ( } #[cfg_attr(c_bindings, allow(dead_code))] - pub(crate) fn clear_signing_pubkey($($self_mut)* $self: $self_type) -> $return_type { - $self.offer.signing_pubkey = None; + pub(crate) fn clear_issuer_signing_pubkey($($self_mut)* $self: $self_type) -> $return_type { + $self.offer.issuer_signing_pubkey = None; $return_value } @@ -570,7 +570,7 @@ pub(super) struct OfferContents { issuer: Option, paths: Option>, supported_quantity: Quantity, - signing_pubkey: Option, + issuer_signing_pubkey: Option, } macro_rules! offer_accessors { ($self: ident, $contents: expr) => { @@ -632,8 +632,8 @@ macro_rules! offer_accessors { ($self: ident, $contents: expr) => { } /// The public key used by the recipient to sign invoices. - pub fn signing_pubkey(&$self) -> Option { - $contents.signing_pubkey() + pub fn issuer_signing_pubkey(&$self) -> Option { + $contents.issuer_signing_pubkey() } } } @@ -916,8 +916,8 @@ impl OfferContents { } } - pub(super) fn signing_pubkey(&self) -> Option { - self.signing_pubkey + pub(super) fn issuer_signing_pubkey(&self) -> Option { + self.issuer_signing_pubkey } pub(super) fn verify_using_metadata( @@ -943,11 +943,11 @@ impl OfferContents { let tlv_stream = TlvStream::new(bytes).range(OFFER_TYPES).filter(|record| { match record.r#type { OFFER_METADATA_TYPE => false, - OFFER_NODE_ID_TYPE => !metadata.derives_recipient_keys(), + OFFER_ISSUER_ID_TYPE => !metadata.derives_recipient_keys(), _ => true, } }); - let signing_pubkey = match self.signing_pubkey() { + let signing_pubkey = match self.issuer_signing_pubkey() { Some(signing_pubkey) => signing_pubkey, None => return Err(()), }; @@ -987,7 +987,7 @@ impl OfferContents { paths: self.paths.as_ref(), issuer: self.issuer.as_ref(), quantity_max: self.supported_quantity.to_tlv_record(), - node_id: self.signing_pubkey.as_ref(), + issuer_id: self.issuer_signing_pubkey.as_ref(), } } } @@ -1063,8 +1063,8 @@ pub(super) const OFFER_TYPES: core::ops::Range = 1..80; /// TLV record type for [`Offer::metadata`]. const OFFER_METADATA_TYPE: u64 = 4; -/// TLV record type for [`Offer::signing_pubkey`]. -const OFFER_NODE_ID_TYPE: u64 = 22; +/// TLV record type for [`Offer::issuer_signing_pubkey`]. +const OFFER_ISSUER_ID_TYPE: u64 = 22; tlv_stream!(OfferTlvStream, OfferTlvStreamRef, OFFER_TYPES, { (2, chains: (Vec, WithoutLength)), @@ -1077,7 +1077,7 @@ tlv_stream!(OfferTlvStream, OfferTlvStreamRef, OFFER_TYPES, { (16, paths: (Vec, WithoutLength)), (18, issuer: (String, WithoutLength)), (20, quantity_max: (u64, HighZeroBytesDroppedBigSize)), - (OFFER_NODE_ID_TYPE, node_id: PublicKey), + (OFFER_ISSUER_ID_TYPE, issuer_id: PublicKey), }); impl Bech32Encode for Offer { @@ -1111,7 +1111,7 @@ impl TryFrom for OfferContents { fn try_from(tlv_stream: OfferTlvStream) -> Result { let OfferTlvStream { chains, metadata, currency, amount, description, features, absolute_expiry, paths, - issuer, quantity_max, node_id, + issuer, quantity_max, issuer_id, } = tlv_stream; let metadata = metadata.map(|metadata| Metadata::Bytes(metadata)); @@ -1141,15 +1141,15 @@ impl TryFrom for OfferContents { Some(n) => Quantity::Bounded(NonZeroU64::new(n).unwrap()), }; - let (signing_pubkey, paths) = match (node_id, paths) { - (None, None) => return Err(Bolt12SemanticError::MissingSigningPubkey), + let (issuer_signing_pubkey, paths) = match (issuer_id, paths) { + (None, None) => return Err(Bolt12SemanticError::MissingIssuerSigningPubkey), (_, Some(paths)) if paths.is_empty() => return Err(Bolt12SemanticError::MissingPaths), - (node_id, paths) => (node_id, paths), + (issuer_id, paths) => (issuer_id, paths), }; Ok(OfferContents { chains, metadata, amount, description, features, absolute_expiry, issuer, paths, - supported_quantity, signing_pubkey, + supported_quantity, issuer_signing_pubkey, }) } } @@ -1210,7 +1210,7 @@ mod tests { assert_eq!(offer.issuer(), None); assert_eq!(offer.supported_quantity(), Quantity::One); assert!(!offer.expects_quantity()); - assert_eq!(offer.signing_pubkey(), Some(pubkey(42))); + assert_eq!(offer.issuer_signing_pubkey(), Some(pubkey(42))); assert_eq!( offer.as_tlv_stream(), @@ -1225,7 +1225,7 @@ mod tests { paths: None, issuer: None, quantity_max: None, - node_id: Some(&pubkey(42)), + issuer_id: Some(&pubkey(42)), }, ); @@ -1307,7 +1307,7 @@ mod tests { .amount_msats(1000) .build().unwrap(); assert!(offer.metadata().is_some()); - assert_eq!(offer.signing_pubkey(), Some(node_id)); + assert_eq!(offer.issuer_signing_pubkey(), Some(node_id)); let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap() .build().unwrap() @@ -1376,7 +1376,7 @@ mod tests { .path(blinded_path) .build().unwrap(); assert!(offer.metadata().is_none()); - assert_ne!(offer.signing_pubkey(), Some(node_id)); + assert_ne!(offer.issuer_signing_pubkey(), Some(node_id)); let invoice_request = offer.request_invoice(vec![1; 32], payer_pubkey()).unwrap() .build().unwrap() @@ -1409,8 +1409,8 @@ mod tests { // Fails verification with altered signing pubkey let mut tlv_stream = offer.as_tlv_stream(); - let signing_pubkey = pubkey(1); - tlv_stream.node_id = Some(&signing_pubkey); + let issuer_id = pubkey(1); + tlv_stream.issuer_id = Some(&issuer_id); let mut encoded_offer = Vec::new(); tlv_stream.write(&mut encoded_offer).unwrap(); @@ -1567,10 +1567,10 @@ mod tests { .unwrap(); let tlv_stream = offer.as_tlv_stream(); assert_eq!(offer.paths(), paths.as_slice()); - assert_eq!(offer.signing_pubkey(), Some(pubkey(42))); + assert_eq!(offer.issuer_signing_pubkey(), Some(pubkey(42))); assert_ne!(pubkey(42), pubkey(44)); assert_eq!(tlv_stream.paths, Some(&paths)); - assert_eq!(tlv_stream.node_id, Some(&pubkey(42))); + assert_eq!(tlv_stream.issuer_id, Some(&pubkey(42))); } #[test] @@ -1773,7 +1773,7 @@ mod tests { BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] }, ] )) - .clear_signing_pubkey() + .clear_issuer_signing_pubkey() .build() .unwrap(); if let Err(e) = offer.to_string().parse::() { @@ -1828,14 +1828,14 @@ mod tests { } #[test] - fn parses_offer_with_node_id() { + fn parses_offer_with_issuer_id() { let offer = OfferBuilder::new(pubkey(42)).build().unwrap(); if let Err(e) = offer.to_string().parse::() { panic!("error parsing offer: {:?}", e); } let mut tlv_stream = offer.as_tlv_stream(); - tlv_stream.node_id = None; + tlv_stream.issuer_id = None; let mut encoded_offer = Vec::new(); tlv_stream.write(&mut encoded_offer).unwrap(); @@ -1843,7 +1843,7 @@ mod tests { match Offer::try_from(encoded_offer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey)); + assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingIssuerSigningPubkey)); }, } } @@ -1948,7 +1948,7 @@ mod bolt12_tests { // Malformed: empty assert_eq!( "lno1".parse::(), - Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey)), + Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingIssuerSigningPubkey)), ); // Malformed: truncated at type @@ -2053,7 +2053,7 @@ mod bolt12_tests { Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)), ); - // Malformed: invalid offer_node_id + // Malformed: invalid offer_issuer_id assert_eq!( "lno1pgz5znzfgdz3vggzqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvps".parse::(), Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)), @@ -2078,10 +2078,10 @@ mod bolt12_tests { Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription)), ); - // Missing offer_node_id" + // Missing offer_issuer_id assert_eq!( "lno1pgx9getnwss8vetrw3hhyuc".parse::(), - Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey)), + Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingIssuerSigningPubkey)), ); } } diff --git a/lightning/src/offers/parse.rs b/lightning/src/offers/parse.rs index 8b9f64d8b..d6661c3cb 100644 --- a/lightning/src/offers/parse.rs +++ b/lightning/src/offers/parse.rs @@ -157,12 +157,10 @@ pub enum Bolt12SemanticError { UnexpectedFeatures, /// A required description was not provided. MissingDescription, - /// A signing pubkey was not provided. - MissingSigningPubkey, - /// A signing pubkey was provided but a different one was expected. - InvalidSigningPubkey, - /// A signing pubkey was provided but was not expected. - UnexpectedSigningPubkey, + /// An issuer's signing pubkey was not provided. + MissingIssuerSigningPubkey, + /// An issuer's signing pubkey was provided but was not expected. + UnexpectedIssuerSigningPubkey, /// A quantity was expected but was missing. MissingQuantity, /// An unsupported quantity was provided. @@ -191,6 +189,10 @@ pub enum Bolt12SemanticError { MissingPaymentHash, /// An invoice payment hash was provided but was not expected. UnexpectedPaymentHash, + /// A signing pubkey was not provided. + MissingSigningPubkey, + /// A signing pubkey was provided but a different one was expected. + InvalidSigningPubkey, /// A signature was expected but was missing. MissingSignature, } diff --git a/lightning/src/offers/refund.rs b/lightning/src/offers/refund.rs index c07055c5c..cf5ed5528 100644 --- a/lightning/src/offers/refund.rs +++ b/lightning/src/offers/refund.rs @@ -752,7 +752,7 @@ impl RefundContents { paths: None, issuer: self.issuer.as_ref(), quantity_max: None, - node_id: None, + issuer_id: None, }; let features = { @@ -844,7 +844,7 @@ impl TryFrom for RefundContents { OfferTlvStream { chains, metadata, currency, amount: offer_amount, description, features: offer_features, absolute_expiry, paths: offer_paths, issuer, quantity_max, - node_id, + issuer_id, }, InvoiceRequestTlvStream { chain, amount, features, quantity, payer_id, payer_note, paths @@ -887,8 +887,8 @@ impl TryFrom for RefundContents { return Err(Bolt12SemanticError::UnexpectedQuantity); } - if node_id.is_some() { - return Err(Bolt12SemanticError::UnexpectedSigningPubkey); + if issuer_id.is_some() { + return Err(Bolt12SemanticError::UnexpectedIssuerSigningPubkey); } let amount_msats = match amount { @@ -1003,7 +1003,7 @@ mod tests { paths: None, issuer: None, quantity_max: None, - node_id: None, + issuer_id: None, }, InvoiceRequestTlvStreamRef { chain: None, @@ -1509,14 +1509,14 @@ mod tests { }, } - let node_id = payer_pubkey(); + let issuer_id = payer_pubkey(); let mut tlv_stream = refund.as_tlv_stream(); - tlv_stream.1.node_id = Some(&node_id); + tlv_stream.1.issuer_id = Some(&issuer_id); match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedSigningPubkey)); + assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedIssuerSigningPubkey)); }, } } diff --git a/lightning/src/offers/static_invoice.rs b/lightning/src/offers/static_invoice.rs index 4910c57c5..2163d5ef4 100644 --- a/lightning/src/offers/static_invoice.rs +++ b/lightning/src/offers/static_invoice.rs @@ -110,8 +110,8 @@ impl<'a> StaticInvoiceBuilder<'a> { return Err(Bolt12SemanticError::MissingPaths); } - let offer_signing_pubkey = - offer.signing_pubkey().ok_or(Bolt12SemanticError::MissingSigningPubkey)?; + let issuer_signing_pubkey = + offer.issuer_signing_pubkey().ok_or(Bolt12SemanticError::MissingIssuerSigningPubkey)?; let keys = offer .verify(nonce, &expanded_key, &secp_ctx) @@ -120,7 +120,7 @@ impl<'a> StaticInvoiceBuilder<'a> { .ok_or(Bolt12SemanticError::MissingSigningPubkey)?; let signing_pubkey = keys.public_key(); - if signing_pubkey != offer_signing_pubkey { + if signing_pubkey != issuer_signing_pubkey { return Err(Bolt12SemanticError::InvalidSigningPubkey); } @@ -707,11 +707,9 @@ mod tests { assert!(invoice.fallbacks().is_empty()); assert_eq!(invoice.invoice_features(), &Bolt12InvoiceFeatures::empty()); - let offer_signing_pubkey = offer.signing_pubkey().unwrap(); + let signing_pubkey = offer.issuer_signing_pubkey().unwrap(); let message = TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &invoice.bytes); - assert!( - merkle::verify_signature(&invoice.signature, &message, offer_signing_pubkey).is_ok() - ); + assert!(merkle::verify_signature(&invoice.signature, &message, signing_pubkey).is_ok()); let paths = vec![blinded_path()]; assert_eq!( @@ -728,7 +726,7 @@ mod tests { paths: Some(&paths), issuer: None, quantity_max: None, - node_id: Some(&offer_signing_pubkey), + issuer_id: Some(&signing_pubkey), }, InvoiceTlvStreamRef { paths: Some(Iterable( @@ -741,7 +739,7 @@ mod tests { amount: None, fallbacks: None, features: None, - node_id: Some(&offer_signing_pubkey), + node_id: Some(&signing_pubkey), message_paths: Some(&paths), }, SignatureTlvStreamRef { signature: Some(&invoice.signature()) }, @@ -880,7 +878,7 @@ mod tests { } #[test] - fn fails_build_offer_signing_pubkey() { + fn fails_building_with_missing_issuer_signing_pubkey() { let node_id = recipient_pubkey(); let now = now(); let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32])); @@ -894,16 +892,15 @@ mod tests { .build() .unwrap(); - // Error if offer signing pubkey is missing. - let mut offer_missing_signing_pubkey = valid_offer.clone(); - let mut offer_tlv_stream = offer_missing_signing_pubkey.as_tlv_stream(); - offer_tlv_stream.node_id.take(); + let mut offer_missing_issuer_id = valid_offer.clone(); + let mut offer_tlv_stream = offer_missing_issuer_id.as_tlv_stream(); + offer_tlv_stream.issuer_id.take(); let mut buffer = Vec::new(); offer_tlv_stream.write(&mut buffer).unwrap(); - offer_missing_signing_pubkey = Offer::try_from(buffer).unwrap(); + offer_missing_issuer_id = Offer::try_from(buffer).unwrap(); if let Err(e) = StaticInvoiceBuilder::for_offer_using_derived_keys( - &offer_missing_signing_pubkey, + &offer_missing_issuer_id, payment_paths(), vec![blinded_path()], now, @@ -911,12 +908,20 @@ mod tests { nonce, &secp_ctx, ) { - assert_eq!(e, Bolt12SemanticError::MissingSigningPubkey); + assert_eq!(e, Bolt12SemanticError::MissingIssuerSigningPubkey); } else { panic!("expected error") } + } + + #[test] + fn fails_building_with_invalid_metadata() { + let now = now(); + let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32])); + let entropy = FixedEntropy {}; + let nonce = Nonce::from_entropy_source(&entropy); + let secp_ctx = Secp256k1::new(); - // Error if the offer's metadata cannot be verified. let offer = OfferBuilder::new(recipient_pubkey()) .path(blinded_path()) .metadata(vec![42; 32]) -- 2.39.5