Skip to content

Commit b1ad951

Browse files
committed
Add c_bindings version of RefundBuilder
Use the macros introduced in the previous commit to define a builder called RefundMaybeWithDerivedMetadataBuilder. The difference between this and RefundBuilder is that this has methods that take `self` by mutable reference instead of by value and don't return anything instead returning the modified builder. This is required because bindings don't support move semantics. Because of this, the builder's contents must be cloned when building a Refund. Keeps RefundBuilder defined so that it can be used internally in ChannelManager::create_refund_builder even when compiled for c_bindings.
1 parent 1af5c40 commit b1ad951

File tree

3 files changed

+104
-46
lines changed

3 files changed

+104
-46
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ use {
8585
#[cfg(c_bindings)]
8686
use {
8787
crate::offers::offer::OfferWithDerivedMetadataBuilder,
88+
crate::offers::refund::RefundMaybeWithDerivedMetadataBuilder,
8889
};
8990

9091
use alloc::collections::{btree_map, BTreeMap};
@@ -7574,23 +7575,7 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
75747575
}
75757576
} }
75767577

7577-
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref> ChannelManager<M, T, ES, NS, SP, F, R, L>
7578-
where
7579-
M::Target: chain::Watch<<SP::Target as SignerProvider>::EcdsaSigner>,
7580-
T::Target: BroadcasterInterface,
7581-
ES::Target: EntropySource,
7582-
NS::Target: NodeSigner,
7583-
SP::Target: SignerProvider,
7584-
F::Target: FeeEstimator,
7585-
R::Target: Router,
7586-
L::Target: Logger,
7587-
{
7588-
#[cfg(not(c_bindings))]
7589-
create_offer_builder!(self, OfferBuilder<DerivedMetadata, secp256k1::All>);
7590-
7591-
#[cfg(c_bindings)]
7592-
create_offer_builder!(self, OfferWithDerivedMetadataBuilder);
7593-
7578+
macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
75947579
/// Creates a [`RefundBuilder`] such that the [`Refund`] it builds is recognized by the
75957580
/// [`ChannelManager`] when handling [`Bolt12Invoice`] messages for the refund.
75967581
///
@@ -7640,31 +7625,53 @@ where
76407625
/// [`Bolt12Invoice::payment_paths`]: crate::offers::invoice::Bolt12Invoice::payment_paths
76417626
/// [Avoiding Duplicate Payments]: #avoiding-duplicate-payments
76427627
pub fn create_refund_builder(
7643-
&self, description: String, amount_msats: u64, absolute_expiry: Duration,
7628+
&$self, description: String, amount_msats: u64, absolute_expiry: Duration,
76447629
payment_id: PaymentId, retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>
7645-
) -> Result<RefundBuilder<secp256k1::All>, Bolt12SemanticError> {
7646-
let node_id = self.get_our_node_id();
7647-
let expanded_key = &self.inbound_payment_key;
7648-
let entropy = &*self.entropy_source;
7649-
let secp_ctx = &self.secp_ctx;
7630+
) -> Result<$builder, Bolt12SemanticError> {
7631+
let node_id = $self.get_our_node_id();
7632+
let expanded_key = &$self.inbound_payment_key;
7633+
let entropy = &*$self.entropy_source;
7634+
let secp_ctx = &$self.secp_ctx;
76507635

7651-
let path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
7636+
let path = $self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
76527637
let builder = RefundBuilder::deriving_payer_id(
76537638
description, node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
76547639
)?
7655-
.chain_hash(self.chain_hash)
7640+
.chain_hash($self.chain_hash)
76567641
.absolute_expiry(absolute_expiry)
76577642
.path(path);
76587643

76597644
let expiration = StaleExpiration::AbsoluteTimeout(absolute_expiry);
7660-
self.pending_outbound_payments
7645+
$self.pending_outbound_payments
76617646
.add_new_awaiting_invoice(
76627647
payment_id, expiration, retry_strategy, max_total_routing_fee_msat,
76637648
)
76647649
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
76657650

7666-
Ok(builder)
7651+
Ok(builder.into())
76677652
}
7653+
} }
7654+
7655+
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref> ChannelManager<M, T, ES, NS, SP, F, R, L>
7656+
where
7657+
M::Target: chain::Watch<<SP::Target as SignerProvider>::EcdsaSigner>,
7658+
T::Target: BroadcasterInterface,
7659+
ES::Target: EntropySource,
7660+
NS::Target: NodeSigner,
7661+
SP::Target: SignerProvider,
7662+
F::Target: FeeEstimator,
7663+
R::Target: Router,
7664+
L::Target: Logger,
7665+
{
7666+
#[cfg(not(c_bindings))]
7667+
create_offer_builder!(self, OfferBuilder<DerivedMetadata, secp256k1::All>);
7668+
#[cfg(not(c_bindings))]
7669+
create_refund_builder!(self, RefundBuilder<secp256k1::All>);
7670+
7671+
#[cfg(c_bindings)]
7672+
create_offer_builder!(self, OfferWithDerivedMetadataBuilder);
7673+
#[cfg(c_bindings)]
7674+
create_refund_builder!(self, RefundMaybeWithDerivedMetadataBuilder);
76687675

76697676
/// Pays for an [`Offer`] using the given parameters by creating an [`InvoiceRequest`] and
76707677
/// enqueuing it to be sent via an onion message. [`ChannelManager`] will pay the actual

lightning/src/offers/invoice.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1310,14 +1310,15 @@ mod tests {
13101310
#[cfg(not(c_bindings))]
13111311
use {
13121312
crate::offers::offer::OfferBuilder,
1313+
crate::offers::refund::RefundBuilder,
13131314
};
13141315
#[cfg(c_bindings)]
13151316
use {
13161317
crate::offers::offer::OfferWithExplicitMetadataBuilder as OfferBuilder,
1318+
crate::offers::refund::RefundMaybeWithDerivedMetadataBuilder as RefundBuilder,
13171319
};
13181320
use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError};
13191321
use crate::offers::payer::PayerTlvStreamRef;
1320-
use crate::offers::refund::RefundBuilder;
13211322
use crate::offers::test_utils::*;
13221323
use crate::util::ser::{BigSize, Iterable, Writeable};
13231324
use crate::util::string::PrintableString;

lightning/src/offers/refund.rs

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,18 @@ pub struct RefundBuilder<'a, T: secp256k1::Signing> {
124124
secp_ctx: Option<&'a Secp256k1<T>>,
125125
}
126126

127-
macro_rules! refund_without_secp256k1_builder_methods { () => {
127+
/// Builds a [`Refund`] for the "offer for money" flow.
128+
///
129+
/// See [module-level documentation] for usage.
130+
///
131+
/// [module-level documentation]: self
132+
#[cfg(c_bindings)]
133+
pub struct RefundMaybeWithDerivedMetadataBuilder<'a> {
134+
refund: RefundContents,
135+
secp_ctx: Option<&'a Secp256k1<secp256k1::All>>,
136+
}
137+
138+
macro_rules! refund_explicit_metadata_builder_methods { () => {
128139
/// Creates a new builder for a refund using the [`Refund::payer_id`] for the public node id to
129140
/// send to if no [`Refund::paths`] are set. Otherwise, it may be a transient pubkey.
130141
///
@@ -158,7 +169,7 @@ macro_rules! refund_without_secp256k1_builder_methods { () => {
158169
} }
159170

160171
macro_rules! refund_builder_methods { (
161-
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr
172+
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr, $secp_context: ty $(, $self_mut: tt)?
162173
) => {
163174
/// Similar to [`RefundBuilder::new`] except, if [`RefundBuilder::path`] is called, the payer id
164175
/// is derived from the given [`ExpandedKey`] and nonce. This provides sender privacy by using a
@@ -175,7 +186,7 @@ macro_rules! refund_builder_methods { (
175186
/// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey
176187
pub fn deriving_payer_id<ES: Deref>(
177188
description: String, node_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES,
178-
secp_ctx: &'a Secp256k1<T>, amount_msats: u64, payment_id: PaymentId
189+
secp_ctx: &'a Secp256k1<$secp_context>, amount_msats: u64, payment_id: PaymentId
179190
) -> Result<Self, Bolt12SemanticError> where ES::Target: EntropySource {
180191
if amount_msats > MAX_VALUE_MSAT {
181192
return Err(Bolt12SemanticError::InvalidAmount);
@@ -199,15 +210,15 @@ macro_rules! refund_builder_methods { (
199210
/// already passed is valid and can be checked for using [`Refund::is_expired`].
200211
///
201212
/// Successive calls to this method will override the previous setting.
202-
pub fn absolute_expiry(mut $self: $self_type, absolute_expiry: Duration) -> $return_type {
213+
pub fn absolute_expiry($($self_mut)* $self: $self_type, absolute_expiry: Duration) -> $return_type {
203214
$self.refund.absolute_expiry = Some(absolute_expiry);
204215
$return_value
205216
}
206217

207218
/// Sets the [`Refund::issuer`].
208219
///
209220
/// Successive calls to this method will override the previous setting.
210-
pub fn issuer(mut $self: $self_type, issuer: String) -> $return_type {
221+
pub fn issuer($($self_mut)* $self: $self_type, issuer: String) -> $return_type {
211222
$self.refund.issuer = Some(issuer);
212223
$return_value
213224
}
@@ -217,7 +228,7 @@ macro_rules! refund_builder_methods { (
217228
///
218229
/// Successive calls to this method will add another blinded path. Caller is responsible for not
219230
/// adding duplicate paths.
220-
pub fn path(mut $self: $self_type, path: BlindedPath) -> $return_type {
231+
pub fn path($($self_mut)* $self: $self_type, path: BlindedPath) -> $return_type {
221232
$self.refund.paths.get_or_insert_with(Vec::new).push(path);
222233
$return_value
223234
}
@@ -234,7 +245,7 @@ macro_rules! refund_builder_methods { (
234245
/// [`Network::Bitcoin`] is assumed.
235246
///
236247
/// Successive calls to this method will override the previous setting.
237-
pub(crate) fn chain_hash(mut $self: $self_type, chain: ChainHash) -> $return_type {
248+
pub(crate) fn chain_hash($($self_mut)* $self: $self_type, chain: ChainHash) -> $return_type {
238249
$self.refund.chain = Some(chain);
239250
$return_value
240251
}
@@ -248,21 +259,21 @@ macro_rules! refund_builder_methods { (
248259
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
249260
/// [`InvoiceRequest::quantity`]: crate::offers::invoice_request::InvoiceRequest::quantity
250261
/// [`Offer`]: crate::offers::offer::Offer
251-
pub fn quantity(mut $self: $self_type, quantity: u64) -> $return_type {
262+
pub fn quantity($($self_mut)* $self: $self_type, quantity: u64) -> $return_type {
252263
$self.refund.quantity = Some(quantity);
253264
$return_value
254265
}
255266

256267
/// Sets the [`Refund::payer_note`].
257268
///
258269
/// Successive calls to this method will override the previous setting.
259-
pub fn payer_note(mut $self: $self_type, payer_note: String) -> $return_type {
270+
pub fn payer_note($($self_mut)* $self: $self_type, payer_note: String) -> $return_type {
260271
$self.refund.payer_note = Some(payer_note);
261272
$return_value
262273
}
263274

264275
/// Builds a [`Refund`] after checking for valid semantics.
265-
pub fn build(mut $self: $self_type) -> Result<Refund, Bolt12SemanticError> {
276+
pub fn build($($self_mut)* $self: $self_type) -> Result<Refund, Bolt12SemanticError> {
266277
if $self.refund.chain() == $self.refund.implied_chain() {
267278
$self.refund.chain = None;
268279
}
@@ -293,34 +304,65 @@ macro_rules! refund_builder_methods { (
293304
let mut bytes = Vec::new();
294305
$self.refund.write(&mut bytes).unwrap();
295306

296-
Ok(Refund { bytes, contents: $self.refund })
307+
Ok(Refund {
308+
bytes,
309+
#[cfg(not(c_bindings))]
310+
contents: $self.refund,
311+
#[cfg(c_bindings)]
312+
contents: $self.refund.clone(),
313+
})
297314
}
298315
} }
299316

300317
#[cfg(test)]
301318
macro_rules! refund_builder_test_methods { (
302-
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr
319+
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr $(, $self_mut: tt)?
303320
) => {
304-
pub(crate) fn clear_paths(mut $self: $self_type) -> $return_type {
321+
#[cfg_attr(c_bindings, allow(dead_code))]
322+
pub(crate) fn clear_paths($($self_mut)* $self: $self_type) -> $return_type {
305323
$self.refund.paths = None;
306324
$return_value
307325
}
308326

309-
fn features_unchecked(mut $self: $self_type, features: InvoiceRequestFeatures) -> $return_type {
327+
#[cfg_attr(c_bindings, allow(dead_code))]
328+
fn features_unchecked($($self_mut)* $self: $self_type, features: InvoiceRequestFeatures) -> $return_type {
310329
$self.refund.features = features;
311330
$return_value
312331
}
313332
} }
314333

315334
impl<'a> RefundBuilder<'a, secp256k1::SignOnly> {
316-
refund_without_secp256k1_builder_methods!();
335+
refund_explicit_metadata_builder_methods!();
317336
}
318337

319338
impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> {
320-
refund_builder_methods!(self, Self, Self, self);
339+
refund_builder_methods!(self, Self, Self, self, T, mut);
321340

322341
#[cfg(test)]
323-
refund_builder_test_methods!(self, Self, Self, self);
342+
refund_builder_test_methods!(self, Self, Self, self, mut);
343+
}
344+
345+
#[cfg(all(c_bindings, not(test)))]
346+
impl<'a> RefundMaybeWithDerivedMetadataBuilder<'a> {
347+
refund_explicit_metadata_builder_methods!();
348+
refund_builder_methods!(self, &mut Self, (), (), secp256k1::All);
349+
}
350+
351+
#[cfg(all(c_bindings, test))]
352+
impl<'a> RefundMaybeWithDerivedMetadataBuilder<'a> {
353+
refund_explicit_metadata_builder_methods!();
354+
refund_builder_methods!(self, &mut Self, &mut Self, self, secp256k1::All);
355+
refund_builder_test_methods!(self, &mut Self, &mut Self, self);
356+
}
357+
358+
#[cfg(c_bindings)]
359+
impl<'a> From<RefundBuilder<'a, secp256k1::All>>
360+
for RefundMaybeWithDerivedMetadataBuilder<'a> {
361+
fn from(builder: RefundBuilder<'a, secp256k1::All>) -> Self {
362+
let RefundBuilder { refund, secp_ctx } = builder;
363+
364+
Self { refund, secp_ctx }
365+
}
324366
}
325367

326368
/// A `Refund` is a request to send an [`Bolt12Invoice`] without a preceding [`Offer`].
@@ -798,7 +840,15 @@ impl core::fmt::Display for Refund {
798840

799841
#[cfg(test)]
800842
mod tests {
801-
use super::{Refund, RefundBuilder, RefundTlvStreamRef};
843+
use super::{Refund, RefundTlvStreamRef};
844+
#[cfg(not(c_bindings))]
845+
use {
846+
super::RefundBuilder,
847+
};
848+
#[cfg(c_bindings)]
849+
use {
850+
super::RefundMaybeWithDerivedMetadataBuilder as RefundBuilder,
851+
};
802852

803853
use bitcoin::blockdata::constants::ChainHash;
804854
use bitcoin::network::constants::Network;

0 commit comments

Comments
 (0)