Skip to content

Commit c000dfc

Browse files
committed
Add c_bindings version of InvoiceRequestBuilder
Use the macros introduced in the previous commit to define two builders for each type parameterization of InvoiceRequestBuilder - InvoiceRequestWithExplicitPayerIdBuilder - InvoiceRequestWithDerivedPayerIdBuilder The difference between these and InvoiceRequestBuilder 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 InvoiceRequest. Keeps InvoiceRequestBuilder defined so that it can be used internally in ChannelManager::pay_for_offer even when compiled for c_bindings.
1 parent d7b93f1 commit c000dfc

File tree

3 files changed

+144
-18
lines changed

3 files changed

+144
-18
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, PaymentA
5959
use crate::ln::wire::Encode;
6060
use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, InvoiceBuilder};
6161
use crate::offers::invoice_error::InvoiceError;
62+
use crate::offers::invoice_request::{DerivedPayerId, InvoiceRequestBuilder};
6263
use crate::offers::merkle::SignError;
6364
use crate::offers::offer::{Offer, OfferBuilder};
6465
use crate::offers::parse::Bolt12SemanticError;
@@ -7735,9 +7736,11 @@ where
77357736
let entropy = &*self.entropy_source;
77367737
let secp_ctx = &self.secp_ctx;
77377738

7738-
let builder = offer
7739+
let builder: InvoiceRequestBuilder<DerivedPayerId, secp256k1::All> = offer
77397740
.request_invoice_deriving_payer_id(expanded_key, entropy, secp_ctx, payment_id)?
7740-
.chain_hash(self.chain_hash)?;
7741+
.into();
7742+
let builder = builder.chain_hash(self.chain_hash)?;
7743+
77417744
let builder = match quantity {
77427745
None => builder,
77437746
Some(quantity) => builder.quantity(quantity)?,

lightning/src/offers/invoice_request.rs

Lines changed: 113 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,12 @@
3636
//! let pubkey = PublicKey::from(keys);
3737
//! let mut buffer = Vec::new();
3838
//!
39+
//! # use lightning::offers::invoice_request::{ExplicitPayerId, InvoiceRequestBuilder};
40+
//! # <InvoiceRequestBuilder<ExplicitPayerId, _>>::from(
3941
//! "lno1qcp4256ypq"
4042
//! .parse::<Offer>()?
4143
//! .request_invoice(vec![42; 64], pubkey)?
44+
//! # )
4245
//! .chain(Network::Testnet)?
4346
//! .amount_msats(1000)?
4447
//! .quantity(5)?
@@ -99,6 +102,34 @@ pub struct InvoiceRequestBuilder<'a, 'b, P: PayerIdStrategy, T: secp256k1::Signi
99102
secp_ctx: Option<&'b Secp256k1<T>>,
100103
}
101104

105+
/// Builds an [`InvoiceRequest`] from an [`Offer`] for the "offer to be paid" flow.
106+
///
107+
/// See [module-level documentation] for usage.
108+
///
109+
/// [module-level documentation]: self
110+
#[cfg(c_bindings)]
111+
pub struct InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b> {
112+
offer: &'a Offer,
113+
invoice_request: InvoiceRequestContentsWithoutPayerId,
114+
payer_id: Option<PublicKey>,
115+
payer_id_strategy: core::marker::PhantomData<ExplicitPayerId>,
116+
secp_ctx: Option<&'b Secp256k1<secp256k1::All>>,
117+
}
118+
119+
/// Builds an [`InvoiceRequest`] from an [`Offer`] for the "offer to be paid" flow.
120+
///
121+
/// See [module-level documentation] for usage.
122+
///
123+
/// [module-level documentation]: self
124+
#[cfg(c_bindings)]
125+
pub struct InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b> {
126+
offer: &'a Offer,
127+
invoice_request: InvoiceRequestContentsWithoutPayerId,
128+
payer_id: Option<PublicKey>,
129+
payer_id_strategy: core::marker::PhantomData<DerivedPayerId>,
130+
secp_ctx: Option<&'b Secp256k1<secp256k1::All>>,
131+
}
132+
102133
/// Indicates how [`InvoiceRequest::payer_id`] will be set.
103134
///
104135
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
@@ -154,10 +185,12 @@ macro_rules! invoice_request_explicit_payer_id_builder_methods { ($self: ident,
154185
}
155186
} }
156187

157-
macro_rules! invoice_request_derived_payer_id_builder_methods { ($self: ident, $self_type: ty) => {
188+
macro_rules! invoice_request_derived_payer_id_builder_methods { (
189+
$self: ident, $self_type: ty, $secp_context: ty
190+
) => {
158191
pub(super) fn deriving_payer_id<ES: Deref>(
159192
offer: &'a Offer, expanded_key: &ExpandedKey, entropy_source: ES,
160-
secp_ctx: &'b Secp256k1<T>, payment_id: PaymentId
193+
secp_ctx: &'b Secp256k1<$secp_context>, payment_id: PaymentId
161194
) -> Self where ES::Target: EntropySource {
162195
let nonce = Nonce::from_entropy_source(entropy_source);
163196
let payment_id = Some(payment_id);
@@ -175,6 +208,8 @@ macro_rules! invoice_request_derived_payer_id_builder_methods { ($self: ident, $
175208
/// Builds a signed [`InvoiceRequest`] after checking for valid semantics.
176209
pub fn build_and_sign($self: $self_type) -> Result<InvoiceRequest, Bolt12SemanticError> {
177210
let (unsigned_invoice_request, keys, secp_ctx) = $self.build_with_checks()?;
211+
#[cfg(c_bindings)]
212+
let mut unsigned_invoice_request = unsigned_invoice_request;
178213
debug_assert!(keys.is_some());
179214

180215
let secp_ctx = secp_ctx.unwrap();
@@ -189,7 +224,7 @@ macro_rules! invoice_request_derived_payer_id_builder_methods { ($self: ident, $
189224
} }
190225

191226
macro_rules! invoice_request_builder_methods { (
192-
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr
227+
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr, $secp_context: ty
193228
) => {
194229
fn create_contents(offer: &Offer, metadata: Metadata) -> InvoiceRequestContentsWithoutPayerId {
195230
let offer = offer.contents.clone();
@@ -255,7 +290,7 @@ macro_rules! invoice_request_builder_methods { (
255290
}
256291

257292
fn build_with_checks(mut $self: $self_type) -> Result<
258-
(UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<T>>),
293+
(UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<$secp_context>>),
259294
Bolt12SemanticError
260295
> {
261296
#[cfg(feature = "std")] {
@@ -286,7 +321,7 @@ macro_rules! invoice_request_builder_methods { (
286321
}
287322

288323
fn build_without_checks(mut $self: $self_type) ->
289-
(UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<T>>)
324+
(UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<$secp_context>>)
290325
{
291326
// Create the metadata for stateless verification of a Bolt12Invoice.
292327
let mut keys = None;
@@ -317,7 +352,10 @@ macro_rules! invoice_request_builder_methods { (
317352
let payer_id = $self.payer_id.unwrap();
318353

319354
let invoice_request = InvoiceRequestContents {
355+
#[cfg(not(c_bindings))]
320356
inner: $self.invoice_request,
357+
#[cfg(c_bindings)]
358+
inner: $self.invoice_request.clone(),
321359
payer_id,
322360
};
323361
let unsigned_invoice_request = UnsignedInvoiceRequest::new($self.offer, invoice_request);
@@ -361,16 +399,70 @@ impl<'a, 'b, T: secp256k1::Signing> InvoiceRequestBuilder<'a, 'b, ExplicitPayerI
361399
}
362400

363401
impl<'a, 'b, T: secp256k1::Signing> InvoiceRequestBuilder<'a, 'b, DerivedPayerId, T> {
364-
invoice_request_derived_payer_id_builder_methods!(self, Self);
402+
invoice_request_derived_payer_id_builder_methods!(self, Self, T);
365403
}
366404

367405
impl<'a, 'b, P: PayerIdStrategy, T: secp256k1::Signing> InvoiceRequestBuilder<'a, 'b, P, T> {
368-
invoice_request_builder_methods!(self, Self, Self, self);
406+
invoice_request_builder_methods!(self, Self, Self, self, T);
369407

370408
#[cfg(test)]
371409
invoice_request_builder_test_methods!(self, Self, Self, self);
372410
}
373411

412+
#[cfg(all(c_bindings, not(test)))]
413+
impl<'a, 'b> InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b> {
414+
invoice_request_explicit_payer_id_builder_methods!(self, &mut Self);
415+
invoice_request_builder_methods!(self, &mut Self, (), (), secp256k1::All);
416+
}
417+
418+
#[cfg(all(c_bindings, test))]
419+
impl<'a, 'b> InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b> {
420+
invoice_request_explicit_payer_id_builder_methods!(self, &mut Self);
421+
invoice_request_builder_methods!(self, &mut Self, &mut Self, self, secp256k1::All);
422+
invoice_request_builder_test_methods!(self, &mut Self, &mut Self, self);
423+
}
424+
425+
#[cfg(all(c_bindings, not(test)))]
426+
impl<'a, 'b> InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b> {
427+
invoice_request_derived_payer_id_builder_methods!(self, &mut Self, secp256k1::All);
428+
invoice_request_builder_methods!(self, &mut Self, (), (), secp256k1::All);
429+
}
430+
431+
#[cfg(all(c_bindings, test))]
432+
impl<'a, 'b> InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b> {
433+
invoice_request_derived_payer_id_builder_methods!(self, &mut Self, secp256k1::All);
434+
invoice_request_builder_methods!(self, &mut Self, &mut Self, self, secp256k1::All);
435+
invoice_request_builder_test_methods!(self, &mut Self, &mut Self, self);
436+
}
437+
438+
#[cfg(c_bindings)]
439+
impl<'a, 'b> From<InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b>>
440+
for InvoiceRequestBuilder<'a, 'b, ExplicitPayerId, secp256k1::All> {
441+
fn from(builder: InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b>) -> Self {
442+
let InvoiceRequestWithExplicitPayerIdBuilder {
443+
offer, invoice_request, payer_id, payer_id_strategy, secp_ctx,
444+
} = builder;
445+
446+
Self {
447+
offer, invoice_request, payer_id, payer_id_strategy, secp_ctx,
448+
}
449+
}
450+
}
451+
452+
#[cfg(c_bindings)]
453+
impl<'a, 'b> From<InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b>>
454+
for InvoiceRequestBuilder<'a, 'b, DerivedPayerId, secp256k1::All> {
455+
fn from(builder: InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b>) -> Self {
456+
let InvoiceRequestWithDerivedPayerIdBuilder {
457+
offer, invoice_request, payer_id, payer_id_strategy, secp_ctx,
458+
} = builder;
459+
460+
Self {
461+
offer, invoice_request, payer_id, payer_id_strategy, secp_ctx,
462+
}
463+
}
464+
}
465+
374466
/// A semantically valid [`InvoiceRequest`] that hasn't been signed.
375467
///
376468
/// # Serialization
@@ -426,17 +518,29 @@ macro_rules! unsigned_invoice_request_sign_method { ($self: ident, $self_type: t
426518
signature_tlv_stream.write(&mut $self.bytes).unwrap();
427519

428520
Ok(InvoiceRequest {
521+
#[cfg(not(c_bindings))]
429522
bytes: $self.bytes,
523+
#[cfg(c_bindings)]
524+
bytes: $self.bytes.clone(),
525+
#[cfg(not(c_bindings))]
430526
contents: $self.contents,
527+
#[cfg(c_bindings)]
528+
contents: $self.contents.clone(),
431529
signature,
432530
})
433531
}
434532
} }
435533

534+
#[cfg(not(c_bindings))]
436535
impl UnsignedInvoiceRequest {
437536
unsigned_invoice_request_sign_method!(self, Self);
438537
}
439538

539+
#[cfg(c_bindings)]
540+
impl UnsignedInvoiceRequest {
541+
unsigned_invoice_request_sign_method!(self, &mut Self);
542+
}
543+
440544
impl AsRef<TaggedHash> for UnsignedInvoiceRequest {
441545
fn as_ref(&self) -> &TaggedHash {
442546
&self.tagged_hash
@@ -984,6 +1088,8 @@ mod tests {
9841088
.build().unwrap()
9851089
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
9861090
.build().unwrap();
1091+
#[cfg(c_bindings)]
1092+
let mut unsigned_invoice_request = unsigned_invoice_request;
9871093

9881094
let mut buffer = Vec::new();
9891095
unsigned_invoice_request.write(&mut buffer).unwrap();

lightning/src/offers/offer.rs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,21 @@ use crate::ln::channelmanager::PaymentId;
9191
use crate::ln::features::OfferFeatures;
9292
use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce};
9393
use crate::ln::msgs::MAX_VALUE_MSAT;
94-
use crate::offers::invoice_request::{DerivedPayerId, ExplicitPayerId, InvoiceRequestBuilder};
9594
use crate::offers::merkle::TlvStream;
9695
use crate::offers::parse::{Bech32Encode, Bolt12ParseError, Bolt12SemanticError, ParsedMessage};
9796
use crate::offers::signer::{Metadata, MetadataMaterial, self};
9897
use crate::util::ser::{HighZeroBytesDroppedBigSize, WithoutLength, Writeable, Writer};
9998
use crate::util::string::PrintableString;
10099

100+
#[cfg(not(c_bindings))]
101+
use {
102+
crate::offers::invoice_request::{DerivedPayerId, ExplicitPayerId, InvoiceRequestBuilder},
103+
};
104+
#[cfg(c_bindings)]
105+
use {
106+
crate::offers::invoice_request::{InvoiceRequestWithDerivedPayerIdBuilder, InvoiceRequestWithExplicitPayerIdBuilder},
107+
};
108+
101109
use crate::prelude::*;
102110

103111
#[cfg(feature = "std")]
@@ -595,14 +603,20 @@ macro_rules! request_invoice_derived_payer_id { ($self: ident, $builder: ty) =>
595603
///
596604
/// Useful to protect the sender's privacy.
597605
///
598-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
599-
///
600606
/// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id
601607
/// [`InvoiceRequest::payer_metadata`]: crate::offers::invoice_request::InvoiceRequest::payer_metadata
602608
/// [`Bolt12Invoice::verify`]: crate::offers::invoice::Bolt12Invoice::verify
603609
/// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey
604-
pub fn request_invoice_deriving_payer_id<'a, 'b, ES: Deref, T: secp256k1::Signing>(
605-
&'a $self, expanded_key: &ExpandedKey, entropy_source: ES, secp_ctx: &'b Secp256k1<T>,
610+
pub fn request_invoice_deriving_payer_id<
611+
'a, 'b, ES: Deref,
612+
#[cfg(not(c_bindings))]
613+
T: secp256k1::Signing
614+
>(
615+
&'a $self, expanded_key: &ExpandedKey, entropy_source: ES,
616+
#[cfg(not(c_bindings))]
617+
secp_ctx: &'b Secp256k1<T>,
618+
#[cfg(c_bindings)]
619+
secp_ctx: &'b Secp256k1<secp256k1::All>,
606620
payment_id: PaymentId
607621
) -> Result<$builder, Bolt12SemanticError>
608622
where
@@ -622,8 +636,6 @@ macro_rules! request_invoice_explicit_payer_id { ($self: ident, $builder: ty) =>
622636
///
623637
/// Useful for recurring payments using the same `payer_id` with different invoices.
624638
///
625-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
626-
///
627639
/// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id
628640
pub fn request_invoice_deriving_metadata<ES: Deref>(
629641
&$self, payer_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES,
@@ -651,8 +663,6 @@ macro_rules! request_invoice_explicit_payer_id { ($self: ident, $builder: ty) =>
651663
///
652664
/// Errors if the offer contains unknown required features.
653665
///
654-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
655-
///
656666
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
657667
pub fn request_invoice(
658668
&$self, metadata: Vec<u8>, payer_id: PublicKey
@@ -665,11 +675,18 @@ macro_rules! request_invoice_explicit_payer_id { ($self: ident, $builder: ty) =>
665675
}
666676
} }
667677

678+
#[cfg(not(c_bindings))]
668679
impl Offer {
669680
request_invoice_derived_payer_id!(self, InvoiceRequestBuilder<'a, 'b, DerivedPayerId, T>);
670681
request_invoice_explicit_payer_id!(self, InvoiceRequestBuilder<ExplicitPayerId, secp256k1::SignOnly>);
671682
}
672683

684+
#[cfg(c_bindings)]
685+
impl Offer {
686+
request_invoice_derived_payer_id!(self, InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b>);
687+
request_invoice_explicit_payer_id!(self, InvoiceRequestWithExplicitPayerIdBuilder);
688+
}
689+
673690
#[cfg(test)]
674691
impl Offer {
675692
pub(super) fn as_tlv_stream(&self) -> OfferTlvStreamRef {

0 commit comments

Comments
 (0)