Skip to content

Commit e70aa38

Browse files
committed
Add c_bindings version of OfferBuilder
Use the macros introduced in the previous commit to define two builders for each type parameterization of OfferBuilder - OfferWithExplicitMetadataBuilder - OfferWithDerivedMetadataBuilder The difference between these and OfferBuilder is that these have 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 nor impl blocks specific to a certain type parameterization. Because of this, the builder's contents must be cloned when building an Offer. Keeps OfferBuilder defined so that it can be used internally in ChannelManager::create_offer_builder even when compiled for c_bindings.
1 parent a517925 commit e70aa38

File tree

4 files changed

+148
-18
lines changed

4 files changed

+148
-18
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ use crate::ln::wire::Encode;
6060
use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, InvoiceBuilder};
6161
use crate::offers::invoice_error::InvoiceError;
6262
use crate::offers::merkle::SignError;
63-
use crate::offers::offer::{DerivedMetadata, Offer, OfferBuilder};
63+
use crate::offers::offer::{Offer, OfferBuilder};
6464
use crate::offers::parse::Bolt12SemanticError;
6565
use crate::offers::refund::{Refund, RefundBuilder};
6666
use crate::onion_message::messenger::{Destination, MessageRouter, PendingOnionMessage, new_pending_onion_message};
@@ -76,11 +76,16 @@ use crate::util::logger::{Level, Logger, WithContext};
7676
use crate::util::errors::APIError;
7777
#[cfg(not(c_bindings))]
7878
use {
79+
crate::offers::offer::DerivedMetadata,
7980
crate::routing::router::DefaultRouter,
8081
crate::routing::gossip::NetworkGraph,
8182
crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters},
8283
crate::sign::KeysManager,
8384
};
85+
#[cfg(c_bindings)]
86+
use {
87+
crate::offers::offer::OfferWithDerivedMetadataBuilder,
88+
};
8489

8590
use alloc::collections::{btree_map, BTreeMap};
8691

@@ -7520,7 +7525,9 @@ where
75207525
self.finish_close_channel(failure);
75217526
}
75227527
}
7528+
}
75237529

7530+
macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
75247531
/// Creates an [`OfferBuilder`] such that the [`Offer`] it builds is recognized by the
75257532
/// [`ChannelManager`] when handling [`InvoiceRequest`] messages for the offer. The offer will
75267533
/// not have an expiration unless otherwise set on the builder.
@@ -7549,22 +7556,40 @@ where
75497556
/// [`Offer`]: crate::offers::offer::Offer
75507557
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
75517558
pub fn create_offer_builder(
7552-
&self, description: String
7553-
) -> Result<OfferBuilder<DerivedMetadata, secp256k1::All>, Bolt12SemanticError> {
7554-
let node_id = self.get_our_node_id();
7555-
let expanded_key = &self.inbound_payment_key;
7556-
let entropy = &*self.entropy_source;
7557-
let secp_ctx = &self.secp_ctx;
7558-
7559-
let path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
7559+
&$self, description: String
7560+
) -> Result<$builder, Bolt12SemanticError> {
7561+
let node_id = $self.get_our_node_id();
7562+
let expanded_key = &$self.inbound_payment_key;
7563+
let entropy = &*$self.entropy_source;
7564+
let secp_ctx = &$self.secp_ctx;
7565+
7566+
let path = $self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
75607567
let builder = OfferBuilder::deriving_signing_pubkey(
75617568
description, node_id, expanded_key, entropy, secp_ctx
75627569
)
7563-
.chain_hash(self.chain_hash)
7570+
.chain_hash($self.chain_hash)
75647571
.path(path);
75657572

7566-
Ok(builder)
7573+
Ok(builder.into())
75677574
}
7575+
} }
7576+
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);
75687593

75697594
/// Creates a [`RefundBuilder`] such that the [`Refund`] it builds is recognized by the
75707595
/// [`ChannelManager`] when handling [`Bolt12Invoice`] messages for the refund.

lightning/src/offers/invoice.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1306,7 +1306,15 @@ mod tests {
13061306
use crate::ln::msgs::DecodeError;
13071307
use crate::offers::invoice_request::InvoiceRequestTlvStreamRef;
13081308
use crate::offers::merkle::{SignError, SignatureTlvStreamRef, TaggedHash, self};
1309-
use crate::offers::offer::{Amount, OfferBuilder, OfferTlvStreamRef, Quantity};
1309+
use crate::offers::offer::{Amount, OfferTlvStreamRef, Quantity};
1310+
#[cfg(not(c_bindings))]
1311+
use {
1312+
crate::offers::offer::OfferBuilder,
1313+
};
1314+
#[cfg(c_bindings)]
1315+
use {
1316+
crate::offers::offer::OfferWithExplicitMetadataBuilder as OfferBuilder,
1317+
};
13101318
use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError};
13111319
use crate::offers::payer::PayerTlvStreamRef;
13121320
use crate::offers::refund::RefundBuilder;
@@ -1644,6 +1652,8 @@ mod tests {
16441652
],
16451653
};
16461654

1655+
#[cfg(c_bindings)]
1656+
use crate::offers::offer::OfferWithDerivedMetadataBuilder as OfferBuilder;
16471657
let offer = OfferBuilder
16481658
::deriving_signing_pubkey(desc, node_id, &expanded_key, &entropy, &secp_ctx)
16491659
.amount_msats(1000)

lightning/src/offers/invoice_request.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,15 @@ mod tests {
941941
use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
942942
use crate::offers::invoice::{Bolt12Invoice, SIGNATURE_TAG as INVOICE_SIGNATURE_TAG};
943943
use crate::offers::merkle::{SignError, SignatureTlvStreamRef, TaggedHash, self};
944-
use crate::offers::offer::{Amount, OfferBuilder, OfferTlvStreamRef, Quantity};
944+
use crate::offers::offer::{Amount, OfferTlvStreamRef, Quantity};
945+
#[cfg(not(c_bindings))]
946+
use {
947+
crate::offers::offer::OfferBuilder,
948+
};
949+
#[cfg(c_bindings)]
950+
use {
951+
crate::offers::offer::OfferWithExplicitMetadataBuilder as OfferBuilder,
952+
};
945953
use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError};
946954
use crate::offers::payer::PayerTlvStreamRef;
947955
use crate::offers::test_utils::*;

lightning/src/offers/offer.rs

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,34 @@ pub struct OfferBuilder<'a, M: MetadataStrategy, T: secp256k1::Signing> {
118118
secp_ctx: Option<&'a Secp256k1<T>>,
119119
}
120120

121+
/// Builds an [`Offer`] for the "offer to be paid" flow.
122+
///
123+
/// See [module-level documentation] for usage.
124+
///
125+
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
126+
///
127+
/// [module-level documentation]: self
128+
#[cfg(c_bindings)]
129+
pub struct OfferWithExplicitMetadataBuilder<'a> {
130+
offer: OfferContents,
131+
metadata_strategy: core::marker::PhantomData<ExplicitMetadata>,
132+
secp_ctx: Option<&'a Secp256k1<secp256k1::All>>,
133+
}
134+
135+
/// Builds an [`Offer`] for the "offer to be paid" flow.
136+
///
137+
/// See [module-level documentation] for usage.
138+
///
139+
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
140+
///
141+
/// [module-level documentation]: self
142+
#[cfg(c_bindings)]
143+
pub struct OfferWithDerivedMetadataBuilder<'a> {
144+
offer: OfferContents,
145+
metadata_strategy: core::marker::PhantomData<DerivedMetadata>,
146+
secp_ctx: Option<&'a Secp256k1<secp256k1::All>>,
147+
}
148+
121149
/// Indicates how [`Offer::metadata`] may be set.
122150
///
123151
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
@@ -174,7 +202,7 @@ macro_rules! offer_explicit_metadata_builder_methods { (
174202
}
175203
} }
176204

177-
macro_rules! offer_derived_metadata_builder_methods { () => {
205+
macro_rules! offer_derived_metadata_builder_methods { ($secp_context: ty) => {
178206
/// Similar to [`OfferBuilder::new`] except, if [`OfferBuilder::path`] is called, the signing
179207
/// pubkey is derived from the given [`ExpandedKey`] and [`EntropySource`]. This provides
180208
/// recipient privacy by using a different signing pubkey for each offer. Otherwise, the
@@ -188,7 +216,7 @@ macro_rules! offer_derived_metadata_builder_methods { () => {
188216
/// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey
189217
pub fn deriving_signing_pubkey<ES: Deref>(
190218
description: String, node_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES,
191-
secp_ctx: &'a Secp256k1<T>
219+
secp_ctx: &'a Secp256k1<$secp_context>
192220
) -> Self where ES::Target: EntropySource {
193221
let nonce = Nonce::from_entropy_source(entropy_source);
194222
let derivation_material = MetadataMaterial::new(nonce, expanded_key, IV_BYTES, None);
@@ -333,7 +361,13 @@ macro_rules! offer_builder_methods { (
333361
let mut bytes = Vec::new();
334362
$self.offer.write(&mut bytes).unwrap();
335363

336-
Offer { bytes, contents: $self.offer }
364+
Offer {
365+
bytes,
366+
#[cfg(not(c_bindings))]
367+
contents: $self.offer,
368+
#[cfg(c_bindings)]
369+
contents: $self.offer.clone()
370+
}
337371
}
338372
} }
339373

@@ -368,7 +402,43 @@ impl<'a> OfferBuilder<'a, ExplicitMetadata, secp256k1::SignOnly> {
368402
}
369403

370404
impl<'a, T: secp256k1::Signing> OfferBuilder<'a, DerivedMetadata, T> {
371-
offer_derived_metadata_builder_methods!();
405+
offer_derived_metadata_builder_methods!(T);
406+
}
407+
408+
#[cfg(all(c_bindings, not(test)))]
409+
impl<'a> OfferWithExplicitMetadataBuilder<'a> {
410+
offer_explicit_metadata_builder_methods!(self, &mut Self, (), ());
411+
offer_builder_methods!(self, &mut Self, (), ());
412+
}
413+
414+
#[cfg(all(c_bindings, test))]
415+
impl<'a> OfferWithExplicitMetadataBuilder<'a> {
416+
offer_explicit_metadata_builder_methods!(self, &mut Self, &mut Self, self);
417+
offer_builder_methods!(self, &mut Self, &mut Self, self);
418+
offer_builder_test_methods!(self, &mut Self, &mut Self, self);
419+
}
420+
421+
#[cfg(all(c_bindings, not(test)))]
422+
impl<'a> OfferWithDerivedMetadataBuilder<'a> {
423+
offer_derived_metadata_builder_methods!(secp256k1::All);
424+
offer_builder_methods!(self, &mut Self, (), ());
425+
}
426+
427+
#[cfg(all(c_bindings, test))]
428+
impl<'a> OfferWithDerivedMetadataBuilder<'a> {
429+
offer_derived_metadata_builder_methods!(secp256k1::All);
430+
offer_builder_methods!(self, &mut Self, &mut Self, self);
431+
offer_builder_test_methods!(self, &mut Self, &mut Self, self);
432+
}
433+
434+
#[cfg(c_bindings)]
435+
impl<'a> From<OfferBuilder<'a, DerivedMetadata, secp256k1::All>>
436+
for OfferWithDerivedMetadataBuilder<'a> {
437+
fn from(builder: OfferBuilder<'a, DerivedMetadata, secp256k1::All>) -> Self {
438+
let OfferBuilder { offer, metadata_strategy, secp_ctx } = builder;
439+
440+
Self { offer, metadata_strategy, secp_ctx }
441+
}
372442
}
373443

374444
/// An `Offer` is a potentially long-lived proposal for payment of a good or service.
@@ -936,7 +1006,15 @@ impl core::fmt::Display for Offer {
9361006

9371007
#[cfg(test)]
9381008
mod tests {
939-
use super::{Amount, Offer, OfferBuilder, OfferTlvStreamRef, Quantity};
1009+
use super::{Amount, Offer, OfferTlvStreamRef, Quantity};
1010+
#[cfg(not(c_bindings))]
1011+
use {
1012+
super::OfferBuilder,
1013+
};
1014+
#[cfg(c_bindings)]
1015+
use {
1016+
super::OfferWithExplicitMetadataBuilder as OfferBuilder,
1017+
};
9401018

9411019
use bitcoin::blockdata::constants::ChainHash;
9421020
use bitcoin::network::constants::Network;
@@ -1065,6 +1143,8 @@ mod tests {
10651143
let entropy = FixedEntropy {};
10661144
let secp_ctx = Secp256k1::new();
10671145

1146+
#[cfg(c_bindings)]
1147+
use super::OfferWithDerivedMetadataBuilder as OfferBuilder;
10681148
let offer = OfferBuilder
10691149
::deriving_signing_pubkey(desc, node_id, &expanded_key, &entropy, &secp_ctx)
10701150
.amount_msats(1000)
@@ -1121,6 +1201,8 @@ mod tests {
11211201
],
11221202
};
11231203

1204+
#[cfg(c_bindings)]
1205+
use super::OfferWithDerivedMetadataBuilder as OfferBuilder;
11241206
let offer = OfferBuilder
11251207
::deriving_signing_pubkey(desc, node_id, &expanded_key, &entropy, &secp_ctx)
11261208
.amount_msats(1000)
@@ -1175,8 +1257,13 @@ mod tests {
11751257
assert_eq!(tlv_stream.amount, Some(1000));
11761258
assert_eq!(tlv_stream.currency, None);
11771259

1260+
#[cfg(not(c_bindings))]
11781261
let builder = OfferBuilder::new("foo".into(), pubkey(42))
11791262
.amount(currency_amount.clone());
1263+
#[cfg(c_bindings)]
1264+
let mut builder = OfferBuilder::new("foo".into(), pubkey(42));
1265+
#[cfg(c_bindings)]
1266+
builder.amount(currency_amount.clone());
11801267
let tlv_stream = builder.offer.as_tlv_stream();
11811268
assert_eq!(builder.offer.amount, Some(currency_amount.clone()));
11821269
assert_eq!(tlv_stream.amount, Some(10));

0 commit comments

Comments
 (0)