Skip to content

Commit 13ff874

Browse files
committed
Add c_bindings version of InvoiceBuilder
Use the macros introduced in the previous commit to define two builders for each type parameterization of InvoiceBuilder - InvoiceWithExplicitSigningPubkeyBuilder - InvoiceWithDerivedSigningPubkeyBuilder The difference between these and InvoiceBuilder 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 a Bolt12Invoice. Keeps InvoiceBuilder defined so that it can be used internally in ChannelManager's OffersMessageHandler even when compiled for c_bindings.
1 parent f84f0a3 commit 13ff874

File tree

3 files changed

+149
-20
lines changed

3 files changed

+149
-20
lines changed

lightning/src/ln/channelmanager.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
5757
use crate::ln::outbound_payment;
5858
use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, PaymentAttempts, PendingOutboundPayment, SendAlongPathArgs, StaleExpiration};
5959
use crate::ln::wire::Encode;
60-
use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, InvoiceBuilder};
60+
use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder};
6161
use crate::offers::invoice_error::InvoiceError;
6262
use crate::offers::invoice_request::{DerivedPayerId, InvoiceRequestBuilder};
6363
use crate::offers::merkle::SignError;
@@ -9281,6 +9281,8 @@ where
92819281
let builder = invoice_request.respond_using_derived_keys_no_std(
92829282
payment_paths, payment_hash, created_at
92839283
);
9284+
let builder: Result<InvoiceBuilder<DerivedSigningPubkey>, _> =
9285+
builder.map(|b| b.into());
92849286
match builder.and_then(|b| b.allow_mpp().build_and_sign(secp_ctx)) {
92859287
Ok(invoice) => Some(OffersMessage::Invoice(invoice)),
92869288
Err(error) => Some(OffersMessage::InvoiceError(error.into())),
@@ -9292,6 +9294,8 @@ where
92929294
let builder = invoice_request.respond_with_no_std(
92939295
payment_paths, payment_hash, created_at
92949296
);
9297+
let builder: Result<InvoiceBuilder<ExplicitSigningPubkey>, _> =
9298+
builder.map(|b| b.into());
92959299
let response = builder.and_then(|builder| builder.allow_mpp().build())
92969300
.map_err(|e| OffersMessage::InvoiceError(e.into()))
92979301
.and_then(|invoice|

lightning/src/offers/invoice.rs

+105-8
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,38 @@ pub struct InvoiceBuilder<'a, S: SigningPubkeyStrategy> {
151151
signing_pubkey_strategy: S,
152152
}
153153

154+
/// Builds a [`Bolt12Invoice`] from either:
155+
/// - an [`InvoiceRequest`] for the "offer to be paid" flow or
156+
/// - a [`Refund`] for the "offer for money" flow.
157+
///
158+
/// See [module-level documentation] for usage.
159+
///
160+
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
161+
/// [`Refund`]: crate::offers::refund::Refund
162+
/// [module-level documentation]: self
163+
#[cfg(c_bindings)]
164+
pub struct InvoiceWithExplicitSigningPubkeyBuilder<'a> {
165+
invreq_bytes: &'a Vec<u8>,
166+
invoice: InvoiceContents,
167+
signing_pubkey_strategy: ExplicitSigningPubkey,
168+
}
169+
170+
/// Builds a [`Bolt12Invoice`] from either:
171+
/// - an [`InvoiceRequest`] for the "offer to be paid" flow or
172+
/// - a [`Refund`] for the "offer for money" flow.
173+
///
174+
/// See [module-level documentation] for usage.
175+
///
176+
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
177+
/// [`Refund`]: crate::offers::refund::Refund
178+
/// [module-level documentation]: self
179+
#[cfg(c_bindings)]
180+
pub struct InvoiceWithDerivedSigningPubkeyBuilder<'a> {
181+
invreq_bytes: &'a Vec<u8>,
182+
invoice: InvoiceContents,
183+
signing_pubkey_strategy: DerivedSigningPubkey,
184+
}
185+
154186
/// Indicates how [`Bolt12Invoice::signing_pubkey`] was set.
155187
///
156188
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
@@ -216,8 +248,13 @@ macro_rules! invoice_explicit_signing_pubkey_builder_methods { ($self: ident, $s
216248
}
217249
}
218250

219-
let InvoiceBuilder { invreq_bytes, invoice, .. } = $self;
220-
Ok(UnsignedBolt12Invoice::new(invreq_bytes, invoice))
251+
let Self { invreq_bytes, invoice, .. } = $self;
252+
#[cfg(not(c_bindings))] {
253+
Ok(UnsignedBolt12Invoice::new(invreq_bytes, invoice))
254+
}
255+
#[cfg(c_bindings)] {
256+
Ok(UnsignedBolt12Invoice::new(invreq_bytes, invoice.clone()))
257+
}
221258
}
222259
} }
223260

@@ -272,10 +309,13 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { (
272309
}
273310
}
274311

275-
let InvoiceBuilder {
312+
let Self {
276313
invreq_bytes, invoice, signing_pubkey_strategy: DerivedSigningPubkey(keys)
277314
} = $self;
315+
#[cfg(not(c_bindings))]
278316
let unsigned_invoice = UnsignedBolt12Invoice::new(invreq_bytes, invoice);
317+
#[cfg(c_bindings)]
318+
let unsigned_invoice = UnsignedBolt12Invoice::new(invreq_bytes, invoice.clone());
279319

280320
let invoice = unsigned_invoice
281321
.sign::<_, Infallible>(
@@ -287,7 +327,7 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { (
287327
} }
288328

289329
macro_rules! invoice_builder_methods { (
290-
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr
330+
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr, $type_param: ty
291331
) => {
292332
pub(crate) fn amount_msats(
293333
invoice_request: &InvoiceRequest
@@ -316,7 +356,7 @@ macro_rules! invoice_builder_methods { (
316356
}
317357

318358
fn new(
319-
invreq_bytes: &'a Vec<u8>, contents: InvoiceContents, signing_pubkey_strategy: S
359+
invreq_bytes: &'a Vec<u8>, contents: InvoiceContents, signing_pubkey_strategy: $type_param
320360
) -> Result<Self, Bolt12SemanticError> {
321361
if contents.fields().payment_paths.is_empty() {
322362
return Err(Bolt12SemanticError::MissingPaths);
@@ -392,7 +432,59 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
392432
}
393433

394434
impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> {
395-
invoice_builder_methods!(self, Self, Self, self);
435+
invoice_builder_methods!(self, Self, Self, self, S);
436+
}
437+
438+
#[cfg(all(c_bindings, not(test)))]
439+
impl<'a> InvoiceWithExplicitSigningPubkeyBuilder<'a> {
440+
invoice_explicit_signing_pubkey_builder_methods!(self, &mut Self);
441+
invoice_builder_methods!(self, &mut Self, (), (), ExplicitSigningPubkey);
442+
}
443+
444+
#[cfg(all(c_bindings, test))]
445+
impl<'a> InvoiceWithExplicitSigningPubkeyBuilder<'a> {
446+
invoice_explicit_signing_pubkey_builder_methods!(self, &mut Self);
447+
invoice_builder_methods!(self, &mut Self, &mut Self, self, ExplicitSigningPubkey);
448+
}
449+
450+
#[cfg(all(c_bindings, not(test)))]
451+
impl<'a> InvoiceWithDerivedSigningPubkeyBuilder<'a> {
452+
invoice_derived_signing_pubkey_builder_methods!(self, &mut Self, secp256k1::All);
453+
invoice_builder_methods!(self, &mut Self, (), (), DerivedSigningPubkey);
454+
}
455+
456+
#[cfg(all(c_bindings, test))]
457+
impl<'a> InvoiceWithDerivedSigningPubkeyBuilder<'a> {
458+
invoice_derived_signing_pubkey_builder_methods!(self, &mut Self, secp256k1::All);
459+
invoice_builder_methods!(self, &mut Self, &mut Self, self, DerivedSigningPubkey);
460+
}
461+
462+
#[cfg(c_bindings)]
463+
impl<'a> From<InvoiceWithDerivedSigningPubkeyBuilder<'a>>
464+
for InvoiceBuilder<'a, DerivedSigningPubkey> {
465+
fn from(builder: InvoiceWithDerivedSigningPubkeyBuilder<'a>) -> Self {
466+
let InvoiceWithDerivedSigningPubkeyBuilder {
467+
invreq_bytes, invoice, signing_pubkey_strategy,
468+
} = builder;
469+
470+
Self {
471+
invreq_bytes, invoice, signing_pubkey_strategy,
472+
}
473+
}
474+
}
475+
476+
#[cfg(c_bindings)]
477+
impl<'a> From<InvoiceWithExplicitSigningPubkeyBuilder<'a>>
478+
for InvoiceBuilder<'a, ExplicitSigningPubkey> {
479+
fn from(builder: InvoiceWithExplicitSigningPubkeyBuilder<'a>) -> Self {
480+
let InvoiceWithExplicitSigningPubkeyBuilder {
481+
invreq_bytes, invoice, signing_pubkey_strategy,
482+
} = builder;
483+
484+
Self {
485+
invreq_bytes, invoice, signing_pubkey_strategy,
486+
}
487+
}
396488
}
397489

398490
/// A semantically valid [`Bolt12Invoice`] that hasn't been signed.
@@ -1685,7 +1777,7 @@ mod tests {
16851777
if let Err(e) = invoice_request.clone()
16861778
.verify(&expanded_key, &secp_ctx).unwrap()
16871779
.respond_using_derived_keys_no_std(payment_paths(), payment_hash(), now()).unwrap()
1688-
.build_and_sign(&secp_ctx)
1780+
.build_and_sign::<secp256k1::All>(&secp_ctx)
16891781
{
16901782
panic!("error building invoice: {:?}", e);
16911783
}
@@ -2122,8 +2214,13 @@ mod tests {
21222214
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
21232215
.build().unwrap()
21242216
.sign(payer_sign).unwrap();
2217+
#[cfg(not(c_bindings))]
2218+
let invoice_builder = invoice_request
2219+
.respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap();
2220+
#[cfg(c_bindings)]
21252221
let mut invoice_builder = invoice_request
2126-
.respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
2222+
.respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap();
2223+
let mut invoice_builder = invoice_builder
21272224
.fallback_v0_p2wsh(&script.wscript_hash())
21282225
.fallback_v0_p2wpkh(&pubkey.wpubkey_hash().unwrap())
21292226
.fallback_v1_p2tr_tweaked(&tweaked_pubkey);

lightning/src/offers/invoice_request.rs

+39-11
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use crate::ln::channelmanager::PaymentId;
6868
use crate::ln::features::InvoiceRequestFeatures;
6969
use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce};
7070
use crate::ln::msgs::DecodeError;
71-
use crate::offers::invoice::{BlindedPayInfo, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder};
71+
use crate::offers::invoice::BlindedPayInfo;
7272
use crate::offers::merkle::{SignError, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, self};
7373
use crate::offers::offer::{Offer, OfferContents, OfferTlvStream, OfferTlvStreamRef};
7474
use crate::offers::parse::{Bolt12ParseError, ParsedMessage, Bolt12SemanticError};
@@ -77,6 +77,15 @@ use crate::offers::signer::{Metadata, MetadataMaterial};
7777
use crate::util::ser::{HighZeroBytesDroppedBigSize, SeekReadable, WithoutLength, Writeable, Writer};
7878
use crate::util::string::PrintableString;
7979

80+
#[cfg(not(c_bindings))]
81+
use {
82+
crate::offers::invoice::{DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder},
83+
};
84+
#[cfg(c_bindings)]
85+
use {
86+
crate::offers::invoice::{InvoiceWithDerivedSigningPubkeyBuilder, InvoiceWithExplicitSigningPubkeyBuilder},
87+
};
88+
8089
use crate::prelude::*;
8190

8291
/// Tag for the hash function used when signing an [`InvoiceRequest`]'s merkle root.
@@ -643,8 +652,6 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { (
643652
/// See [`InvoiceRequest::respond_with_no_std`] for further details where the aforementioned
644653
/// creation time is used for the `created_at` parameter.
645654
///
646-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
647-
///
648655
/// [`Duration`]: core::time::Duration
649656
#[cfg(feature = "std")]
650657
pub fn respond_with(
@@ -678,8 +685,6 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { (
678685
/// If the originating [`Offer`] was created using [`OfferBuilder::deriving_signing_pubkey`],
679686
/// then use [`InvoiceRequest::verify`] and [`VerifiedInvoiceRequest`] methods instead.
680687
///
681-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
682-
///
683688
/// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
684689
/// [`OfferBuilder::deriving_signing_pubkey`]: crate::offers::offer::OfferBuilder::deriving_signing_pubkey
685690
pub fn respond_with_no_std(
@@ -700,24 +705,45 @@ macro_rules! invoice_request_verify_method { ($self: ident, $self_type: ty) => {
700705
/// if they could be extracted from the metadata.
701706
///
702707
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
703-
pub fn verify<T: secp256k1::Signing>(
704-
$self: $self_type, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
708+
pub fn verify<
709+
#[cfg(not(c_bindings))]
710+
T: secp256k1::Signing
711+
>(
712+
$self: $self_type, key: &ExpandedKey,
713+
#[cfg(not(c_bindings))]
714+
secp_ctx: &Secp256k1<T>,
715+
#[cfg(c_bindings)]
716+
secp_ctx: &Secp256k1<secp256k1::All>,
705717
) -> Result<VerifiedInvoiceRequest, ()> {
706718
let keys = $self.contents.inner.offer.verify(&$self.bytes, key, secp_ctx)?;
707719
Ok(VerifiedInvoiceRequest {
720+
#[cfg(not(c_bindings))]
708721
inner: $self,
722+
#[cfg(c_bindings)]
723+
inner: $self.clone(),
709724
keys,
710725
})
711726
}
712727

713728
} }
714729

730+
#[cfg(not(c_bindings))]
715731
impl InvoiceRequest {
716732
offer_accessors!(self, self.contents.inner.offer);
717733
invoice_request_accessors!(self, self.contents);
718734
invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self, InvoiceBuilder<ExplicitSigningPubkey>);
719735
invoice_request_verify_method!(self, Self);
736+
}
720737

738+
#[cfg(c_bindings)]
739+
impl InvoiceRequest {
740+
offer_accessors!(self, self.contents.inner.offer);
741+
invoice_request_accessors!(self, self.contents);
742+
invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self, InvoiceWithExplicitSigningPubkeyBuilder);
743+
invoice_request_verify_method!(self, &Self);
744+
}
745+
746+
impl InvoiceRequest {
721747
/// Signature of the invoice request using [`payer_id`].
722748
///
723749
/// [`payer_id`]: Self::payer_id
@@ -744,8 +770,6 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
744770
///
745771
/// See [`InvoiceRequest::respond_with`] for further details.
746772
///
747-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
748-
///
749773
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
750774
#[cfg(feature = "std")]
751775
pub fn respond_using_derived_keys(
@@ -764,8 +788,6 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
764788
///
765789
/// See [`InvoiceRequest::respond_with_no_std`] for further details.
766790
///
767-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
768-
///
769791
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
770792
pub fn respond_using_derived_keys_no_std(
771793
&$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
@@ -789,8 +811,14 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
789811
impl VerifiedInvoiceRequest {
790812
offer_accessors!(self, self.inner.contents.inner.offer);
791813
invoice_request_accessors!(self, self.inner.contents);
814+
#[cfg(not(c_bindings))]
792815
invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self.inner, InvoiceBuilder<ExplicitSigningPubkey>);
816+
#[cfg(c_bindings)]
817+
invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self.inner, InvoiceWithExplicitSigningPubkeyBuilder);
818+
#[cfg(not(c_bindings))]
793819
invoice_request_respond_with_derived_signing_pubkey_methods!(self, self.inner, InvoiceBuilder<DerivedSigningPubkey>);
820+
#[cfg(c_bindings)]
821+
invoice_request_respond_with_derived_signing_pubkey_methods!(self, self.inner, InvoiceWithDerivedSigningPubkeyBuilder);
794822
}
795823

796824
impl InvoiceRequestContents {

0 commit comments

Comments
 (0)