From: Jeffrey Czyz Date: Fri, 23 Feb 2024 22:52:49 +0000 (-0600) Subject: Macro-ize RefundBuilder X-Git-Tag: v0.0.123-beta~46^2~10 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=1af5c409fe860a8ddabaf3475a29bc83fb068b8a;p=rust-lightning Macro-ize RefundBuilder RefundBuilder is not exported to bindings because it has methods that take `self` by value. Define these methods using macros such that different builders and related methods can be defined for c_bindings. --- diff --git a/lightning/src/offers/refund.rs b/lightning/src/offers/refund.rs index ba3ab1d1e..6d3a34f61 100644 --- a/lightning/src/offers/refund.rs +++ b/lightning/src/offers/refund.rs @@ -124,7 +124,7 @@ pub struct RefundBuilder<'a, T: secp256k1::Signing> { secp_ctx: Option<&'a Secp256k1>, } -impl<'a> RefundBuilder<'a, secp256k1::SignOnly> { +macro_rules! refund_without_secp256k1_builder_methods { () => { /// Creates a new builder for a refund using the [`Refund::payer_id`] for the public node id to /// send to if no [`Refund::paths`] are set. Otherwise, it may be a transient pubkey. /// @@ -155,9 +155,11 @@ impl<'a> RefundBuilder<'a, secp256k1::SignOnly> { secp_ctx: None, }) } -} +} } -impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> { +macro_rules! refund_builder_methods { ( + $self: ident, $self_type: ty, $return_type: ty, $return_value: expr +) => { /// Similar to [`RefundBuilder::new`] except, if [`RefundBuilder::path`] is called, the payer id /// is derived from the given [`ExpandedKey`] and nonce. This provides sender privacy by using a /// different payer id for each refund, assuming a different nonce is used. Otherwise, the @@ -197,17 +199,17 @@ impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> { /// already passed is valid and can be checked for using [`Refund::is_expired`]. /// /// Successive calls to this method will override the previous setting. - pub fn absolute_expiry(mut self, absolute_expiry: Duration) -> Self { - self.refund.absolute_expiry = Some(absolute_expiry); - self + pub fn absolute_expiry(mut $self: $self_type, absolute_expiry: Duration) -> $return_type { + $self.refund.absolute_expiry = Some(absolute_expiry); + $return_value } /// Sets the [`Refund::issuer`]. /// /// Successive calls to this method will override the previous setting. - pub fn issuer(mut self, issuer: String) -> Self { - self.refund.issuer = Some(issuer); - self + pub fn issuer(mut $self: $self_type, issuer: String) -> $return_type { + $self.refund.issuer = Some(issuer); + $return_value } /// Adds a blinded path to [`Refund::paths`]. Must include at least one path if only connected @@ -215,26 +217,26 @@ impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> { /// /// Successive calls to this method will add another blinded path. Caller is responsible for not /// adding duplicate paths. - pub fn path(mut self, path: BlindedPath) -> Self { - self.refund.paths.get_or_insert_with(Vec::new).push(path); - self + pub fn path(mut $self: $self_type, path: BlindedPath) -> $return_type { + $self.refund.paths.get_or_insert_with(Vec::new).push(path); + $return_value } /// Sets the [`Refund::chain`] of the given [`Network`] for paying an invoice. If not /// called, [`Network::Bitcoin`] is assumed. /// /// Successive calls to this method will override the previous setting. - pub fn chain(self, network: Network) -> Self { - self.chain_hash(ChainHash::using_genesis_block(network)) + pub fn chain($self: $self_type, network: Network) -> $return_type { + $self.chain_hash(ChainHash::using_genesis_block(network)) } /// Sets the [`Refund::chain`] of the given [`ChainHash`] for paying an invoice. If not called, /// [`Network::Bitcoin`] is assumed. /// /// Successive calls to this method will override the previous setting. - pub(crate) fn chain_hash(mut self, chain: ChainHash) -> Self { - self.refund.chain = Some(chain); - self + pub(crate) fn chain_hash(mut $self: $self_type, chain: ChainHash) -> $return_type { + $self.refund.chain = Some(chain); + $return_value } /// Sets [`Refund::quantity`] of items. This is purely for informational purposes. It is useful @@ -246,66 +248,79 @@ impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> { /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice /// [`InvoiceRequest::quantity`]: crate::offers::invoice_request::InvoiceRequest::quantity /// [`Offer`]: crate::offers::offer::Offer - pub fn quantity(mut self, quantity: u64) -> Self { - self.refund.quantity = Some(quantity); - self + pub fn quantity(mut $self: $self_type, quantity: u64) -> $return_type { + $self.refund.quantity = Some(quantity); + $return_value } /// Sets the [`Refund::payer_note`]. /// /// Successive calls to this method will override the previous setting. - pub fn payer_note(mut self, payer_note: String) -> Self { - self.refund.payer_note = Some(payer_note); - self + pub fn payer_note(mut $self: $self_type, payer_note: String) -> $return_type { + $self.refund.payer_note = Some(payer_note); + $return_value } /// Builds a [`Refund`] after checking for valid semantics. - pub fn build(mut self) -> Result { - if self.refund.chain() == self.refund.implied_chain() { - self.refund.chain = None; + pub fn build(mut $self: $self_type) -> Result { + if $self.refund.chain() == $self.refund.implied_chain() { + $self.refund.chain = None; } // Create the metadata for stateless verification of a Bolt12Invoice. - if self.refund.payer.0.has_derivation_material() { - let mut metadata = core::mem::take(&mut self.refund.payer.0); + if $self.refund.payer.0.has_derivation_material() { + let mut metadata = core::mem::take(&mut $self.refund.payer.0); - if self.refund.paths.is_none() { + if $self.refund.paths.is_none() { metadata = metadata.without_keys(); } - let mut tlv_stream = self.refund.as_tlv_stream(); + let mut tlv_stream = $self.refund.as_tlv_stream(); tlv_stream.0.metadata = None; if metadata.derives_payer_keys() { tlv_stream.2.payer_id = None; } - let (derived_metadata, keys) = metadata.derive_from(tlv_stream, self.secp_ctx); + let (derived_metadata, keys) = metadata.derive_from(tlv_stream, $self.secp_ctx); metadata = derived_metadata; if let Some(keys) = keys { - self.refund.payer_id = keys.public_key(); + $self.refund.payer_id = keys.public_key(); } - self.refund.payer.0 = metadata; + $self.refund.payer.0 = metadata; } let mut bytes = Vec::new(); - self.refund.write(&mut bytes).unwrap(); + $self.refund.write(&mut bytes).unwrap(); - Ok(Refund { bytes, contents: self.refund }) + Ok(Refund { bytes, contents: $self.refund }) } -} +} } #[cfg(test)] -impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> { - pub(crate) fn clear_paths(mut self) -> Self { - self.refund.paths = None; - self +macro_rules! refund_builder_test_methods { ( + $self: ident, $self_type: ty, $return_type: ty, $return_value: expr +) => { + pub(crate) fn clear_paths(mut $self: $self_type) -> $return_type { + $self.refund.paths = None; + $return_value } - fn features_unchecked(mut self, features: InvoiceRequestFeatures) -> Self { - self.refund.features = features; - self + fn features_unchecked(mut $self: $self_type, features: InvoiceRequestFeatures) -> $return_type { + $self.refund.features = features; + $return_value } +} } + +impl<'a> RefundBuilder<'a, secp256k1::SignOnly> { + refund_without_secp256k1_builder_methods!(); +} + +impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> { + refund_builder_methods!(self, Self, Self, self); + + #[cfg(test)] + refund_builder_test_methods!(self, Self, Self, self); } /// A `Refund` is a request to send an [`Bolt12Invoice`] without a preceding [`Offer`].