From: Jeffrey Czyz Date: Tue, 15 Aug 2023 12:45:06 +0000 (-0500) Subject: Macro-ize Offer accessors for reuse X-Git-Tag: v0.0.117-alpha1~49^2~6 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=66060cae8af6969373bb16b73064b8ea3a7b689a;p=rust-lightning Macro-ize Offer accessors for reuse InvoiceRequest wraps OfferContents, which shouldn't be exposed as it is an implementation detail. Define a macro for Offer accessor methods so that InvoiceRequest and UnsignedInvoiceRequest can also define them. --- diff --git a/lightning/src/offers/mod.rs b/lightning/src/offers/mod.rs index d97632a78..c62702711 100644 --- a/lightning/src/offers/mod.rs +++ b/lightning/src/offers/mod.rs @@ -12,11 +12,13 @@ //! //! Offers are a flexible protocol for Lightning payments. +#[macro_use] +pub mod offer; + pub mod invoice; pub mod invoice_error; pub mod invoice_request; pub mod merkle; -pub mod offer; pub mod parse; mod payer; pub mod refund; diff --git a/lightning/src/offers/offer.rs b/lightning/src/offers/offer.rs index a84c2ff43..1044ac960 100644 --- a/lightning/src/offers/offer.rs +++ b/lightning/src/offers/offer.rs @@ -358,77 +358,86 @@ pub(super) struct OfferContents { signing_pubkey: PublicKey, } -impl Offer { +macro_rules! offer_accessors { ($self: ident, $contents: expr) => { // TODO: Return a slice once ChainHash has constants. // - https://github.com/rust-bitcoin/rust-bitcoin/pull/1283 // - https://github.com/rust-bitcoin/rust-bitcoin/pull/1286 /// The chains that may be used when paying a requested invoice (e.g., bitcoin mainnet). /// Payments must be denominated in units of the minimal lightning-payable unit (e.g., msats) /// for the selected chain. - pub fn chains(&self) -> Vec { - self.contents.chains() - } - - pub(super) fn implied_chain(&self) -> ChainHash { - self.contents.implied_chain() - } - - /// Returns whether the given chain is supported by the offer. - pub fn supports_chain(&self, chain: ChainHash) -> bool { - self.contents.supports_chain(chain) + pub fn chains(&$self) -> Vec<$crate::bitcoin::blockdata::constants::ChainHash> { + $contents.chains() } // TODO: Link to corresponding method in `InvoiceRequest`. /// Opaque bytes set by the originator. Useful for authentication and validating fields since it /// is reflected in `invoice_request` messages along with all the other fields from the `offer`. - pub fn metadata(&self) -> Option<&Vec> { - self.contents.metadata() + pub fn metadata(&$self) -> Option<&Vec> { + $contents.metadata() } /// The minimum amount required for a successful payment of a single item. - pub fn amount(&self) -> Option<&Amount> { - self.contents.amount() + pub fn amount(&$self) -> Option<&$crate::offers::offer::Amount> { + $contents.amount() } /// A complete description of the purpose of the payment. Intended to be displayed to the user /// but with the caveat that it has not been verified in any way. - pub fn description(&self) -> PrintableString { - self.contents.description() + pub fn description(&$self) -> $crate::util::string::PrintableString { + $contents.description() } /// Features pertaining to the offer. - pub fn features(&self) -> &OfferFeatures { - &self.contents.features() + pub fn offer_features(&$self) -> &$crate::ln::features::OfferFeatures { + &$contents.features() } /// Duration since the Unix epoch when an invoice should no longer be requested. /// /// If `None`, the offer does not expire. - pub fn absolute_expiry(&self) -> Option { - self.contents.absolute_expiry() - } - - /// Whether the offer has expired. - #[cfg(feature = "std")] - pub fn is_expired(&self) -> bool { - self.contents.is_expired() + pub fn absolute_expiry(&$self) -> Option { + $contents.absolute_expiry() } /// The issuer of the offer, possibly beginning with `user@domain` or `domain`. Intended to be /// displayed to the user but with the caveat that it has not been verified in any way. - pub fn issuer(&self) -> Option { - self.contents.issuer() + pub fn issuer(&$self) -> Option<$crate::util::string::PrintableString> { + $contents.issuer() } /// Paths to the recipient originating from publicly reachable nodes. Blinded paths provide /// recipient privacy by obfuscating its node id. - pub fn paths(&self) -> &[BlindedPath] { - self.contents.paths() + pub fn paths(&$self) -> &[$crate::blinded_path::BlindedPath] { + $contents.paths() } /// The quantity of items supported. - pub fn supported_quantity(&self) -> Quantity { - self.contents.supported_quantity() + pub fn supported_quantity(&$self) -> $crate::offers::offer::Quantity { + $contents.supported_quantity() + } + + /// The public key used by the recipient to sign invoices. + pub fn signing_pubkey(&$self) -> $crate::bitcoin::secp256k1::PublicKey { + $contents.signing_pubkey() + } +} } + +impl Offer { + offer_accessors!(self, self.contents); + + pub(super) fn implied_chain(&self) -> ChainHash { + self.contents.implied_chain() + } + + /// Returns whether the given chain is supported by the offer. + pub fn supports_chain(&self, chain: ChainHash) -> bool { + self.contents.supports_chain(chain) + } + + /// Whether the offer has expired. + #[cfg(feature = "std")] + pub fn is_expired(&self) -> bool { + self.contents.is_expired() } /// Returns whether the given quantity is valid for the offer. @@ -443,11 +452,6 @@ impl Offer { self.contents.expects_quantity() } - /// The public key used by the recipient to sign invoices. - pub fn signing_pubkey(&self) -> PublicKey { - self.contents.signing_pubkey() - } - /// Similar to [`Offer::request_invoice`] except it: /// - derives the [`InvoiceRequest::payer_id`] such that a different key can be used for each /// request, and @@ -469,7 +473,7 @@ impl Offer { where ES::Target: EntropySource, { - if self.features().requires_unknown_bits() { + if self.offer_features().requires_unknown_bits() { return Err(Bolt12SemanticError::UnknownRequiredFeatures); } @@ -490,7 +494,7 @@ impl Offer { where ES::Target: EntropySource, { - if self.features().requires_unknown_bits() { + if self.offer_features().requires_unknown_bits() { return Err(Bolt12SemanticError::UnknownRequiredFeatures); } @@ -515,7 +519,7 @@ impl Offer { pub fn request_invoice( &self, metadata: Vec, payer_id: PublicKey ) -> Result, Bolt12SemanticError> { - if self.features().requires_unknown_bits() { + if self.offer_features().requires_unknown_bits() { return Err(Bolt12SemanticError::UnknownRequiredFeatures); } @@ -890,7 +894,7 @@ mod tests { assert_eq!(offer.metadata(), None); assert_eq!(offer.amount(), None); assert_eq!(offer.description(), PrintableString("foo")); - assert_eq!(offer.features(), &OfferFeatures::empty()); + assert_eq!(offer.offer_features(), &OfferFeatures::empty()); assert_eq!(offer.absolute_expiry(), None); #[cfg(feature = "std")] assert!(!offer.is_expired()); @@ -1131,7 +1135,7 @@ mod tests { .features_unchecked(OfferFeatures::unknown()) .build() .unwrap(); - assert_eq!(offer.features(), &OfferFeatures::unknown()); + assert_eq!(offer.offer_features(), &OfferFeatures::unknown()); assert_eq!(offer.as_tlv_stream().features, Some(&OfferFeatures::unknown())); let offer = OfferBuilder::new("foo".into(), pubkey(42)) @@ -1139,7 +1143,7 @@ mod tests { .features_unchecked(OfferFeatures::empty()) .build() .unwrap(); - assert_eq!(offer.features(), &OfferFeatures::empty()); + assert_eq!(offer.offer_features(), &OfferFeatures::empty()); assert_eq!(offer.as_tlv_stream().features, None); }