Skip to content

Commit a654d35

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 5d7cfa4 commit a654d35

File tree

4 files changed

+173
-22
lines changed

4 files changed

+173
-22
lines changed

lightning/src/ln/channelmanager.rs

+6-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;
@@ -7834,6 +7834,7 @@ where
78347834
let builder = refund.respond_using_derived_keys_no_std(
78357835
payment_paths, payment_hash, created_at, expanded_key, entropy
78367836
)?;
7837+
let builder: InvoiceBuilder<DerivedSigningPubkey> = builder.into();
78377838
let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
78387839
let reply_path = self.create_blinded_path()
78397840
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
@@ -9281,6 +9282,8 @@ where
92819282
let builder = invoice_request.respond_using_derived_keys_no_std(
92829283
payment_paths, payment_hash, created_at
92839284
);
9285+
let builder: Result<InvoiceBuilder<DerivedSigningPubkey>, _> =
9286+
builder.map(|b| b.into());
92849287
match builder.and_then(|b| b.allow_mpp().build_and_sign(secp_ctx)) {
92859288
Ok(invoice) => Some(OffersMessage::Invoice(invoice)),
92869289
Err(error) => Some(OffersMessage::InvoiceError(error.into())),
@@ -9292,6 +9295,8 @@ where
92929295
let builder = invoice_request.respond_with_no_std(
92939296
payment_paths, payment_hash, created_at
92949297
);
9298+
let builder: Result<InvoiceBuilder<ExplicitSigningPubkey>, _> =
9299+
builder.map(|b| b.into());
92959300
let response = builder.and_then(|builder| builder.allow_mpp().build())
92969301
.map_err(|e| OffersMessage::InvoiceError(e.into()))
92979302
.and_then(|invoice|

lightning/src/offers/invoice.rs

+111-9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
//!
2323
//! use bitcoin::hashes::Hash;
2424
//! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
25+
//! # use lightning::offers::invoice::{ExplicitSigningPubkey, InvoiceBuilder};
2526
//! use core::convert::{Infallible, TryFrom};
2627
//! use lightning::offers::invoice_request::InvoiceRequest;
2728
//! use lightning::offers::refund::Refund;
@@ -44,13 +45,15 @@
4445
//! let mut buffer = Vec::new();
4546
//!
4647
//! // Invoice for the "offer to be paid" flow.
48+
//! # <InvoiceBuilder<ExplicitSigningPubkey>>::from(
4749
//! InvoiceRequest::try_from(bytes)?
4850
#![cfg_attr(feature = "std", doc = "
4951
.respond_with(payment_paths, payment_hash)?
5052
")]
5153
#![cfg_attr(not(feature = "std"), doc = "
5254
.respond_with_no_std(payment_paths, payment_hash, core::time::Duration::from_secs(0))?
5355
")]
56+
//! # )
5457
//! .relative_expiry(3600)
5558
//! .allow_mpp()
5659
//! .fallback_v0_p2wpkh(&wpubkey_hash)
@@ -74,6 +77,7 @@
7477
//! # let mut buffer = Vec::new();
7578
//!
7679
//! // Invoice for the "offer for money" flow.
80+
//! # <InvoiceBuilder<ExplicitSigningPubkey>>::from(
7781
//! "lnr1qcp4256ypq"
7882
//! .parse::<Refund>()?
7983
#![cfg_attr(feature = "std", doc = "
@@ -82,6 +86,7 @@
8286
#![cfg_attr(not(feature = "std"), doc = "
8387
.respond_with_no_std(payment_paths, payment_hash, pubkey, core::time::Duration::from_secs(0))?
8488
")]
89+
//! # )
8590
//! .relative_expiry(3600)
8691
//! .allow_mpp()
8792
//! .fallback_v0_p2wpkh(&wpubkey_hash)
@@ -151,6 +156,38 @@ pub struct InvoiceBuilder<'a, S: SigningPubkeyStrategy> {
151156
signing_pubkey_strategy: S,
152157
}
153158

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

219-
let InvoiceBuilder { invreq_bytes, invoice, .. } = $self;
220-
Ok(UnsignedBolt12Invoice::new(invreq_bytes, invoice))
256+
let Self { invreq_bytes, invoice, .. } = $self;
257+
#[cfg(not(c_bindings))] {
258+
Ok(UnsignedBolt12Invoice::new(invreq_bytes, invoice))
259+
}
260+
#[cfg(c_bindings)] {
261+
Ok(UnsignedBolt12Invoice::new(invreq_bytes, invoice.clone()))
262+
}
221263
}
222264
} }
223265

@@ -272,10 +314,13 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { (
272314
}
273315
}
274316

275-
let InvoiceBuilder {
317+
let Self {
276318
invreq_bytes, invoice, signing_pubkey_strategy: DerivedSigningPubkey(keys)
277319
} = $self;
320+
#[cfg(not(c_bindings))]
278321
let unsigned_invoice = UnsignedBolt12Invoice::new(invreq_bytes, invoice);
322+
#[cfg(c_bindings)]
323+
let unsigned_invoice = UnsignedBolt12Invoice::new(invreq_bytes, invoice.clone());
279324

280325
let invoice = unsigned_invoice
281326
.sign::<_, Infallible>(
@@ -287,7 +332,7 @@ macro_rules! invoice_derived_signing_pubkey_builder_methods { (
287332
} }
288333

289334
macro_rules! invoice_builder_methods { (
290-
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr
335+
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr, $type_param: ty
291336
) => {
292337
pub(crate) fn amount_msats(
293338
invoice_request: &InvoiceRequest
@@ -316,7 +361,7 @@ macro_rules! invoice_builder_methods { (
316361
}
317362

318363
fn new(
319-
invreq_bytes: &'a Vec<u8>, contents: InvoiceContents, signing_pubkey_strategy: S
364+
invreq_bytes: &'a Vec<u8>, contents: InvoiceContents, signing_pubkey_strategy: $type_param
320365
) -> Result<Self, Bolt12SemanticError> {
321366
if contents.fields().payment_paths.is_empty() {
322367
return Err(Bolt12SemanticError::MissingPaths);
@@ -392,7 +437,59 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
392437
}
393438

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

398495
/// A semantically valid [`Bolt12Invoice`] that hasn't been signed.
@@ -1685,7 +1782,7 @@ mod tests {
16851782
if let Err(e) = invoice_request.clone()
16861783
.verify(&expanded_key, &secp_ctx).unwrap()
16871784
.respond_using_derived_keys_no_std(payment_paths(), payment_hash(), now()).unwrap()
1688-
.build_and_sign(&secp_ctx)
1785+
.build_and_sign::<secp256k1::All>(&secp_ctx)
16891786
{
16901787
panic!("error building invoice: {:?}", e);
16911788
}
@@ -1726,7 +1823,7 @@ mod tests {
17261823
payment_paths(), payment_hash(), now(), &expanded_key, &entropy
17271824
)
17281825
.unwrap()
1729-
.build_and_sign(&secp_ctx)
1826+
.build_and_sign::<secp256k1::All>(&secp_ctx)
17301827
{
17311828
panic!("error building invoice: {:?}", e);
17321829
}
@@ -2122,8 +2219,13 @@ mod tests {
21222219
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
21232220
.build().unwrap()
21242221
.sign(payer_sign).unwrap();
2222+
#[cfg(not(c_bindings))]
2223+
let invoice_builder = invoice_request
2224+
.respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap();
2225+
#[cfg(c_bindings)]
21252226
let mut invoice_builder = invoice_request
2126-
.respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
2227+
.respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap();
2228+
let mut invoice_builder = invoice_builder
21272229
.fallback_v0_p2wsh(&script.wscript_hash())
21282230
.fallback_v0_p2wpkh(&pubkey.wpubkey_hash().unwrap())
21292231
.fallback_v1_p2tr_tweaked(&tweaked_pubkey);

lightning/src/offers/invoice_request.rs

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

83+
#[cfg(not(c_bindings))]
84+
use {
85+
crate::offers::invoice::{DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder},
86+
};
87+
#[cfg(c_bindings)]
88+
use {
89+
crate::offers::invoice::{InvoiceWithDerivedSigningPubkeyBuilder, InvoiceWithExplicitSigningPubkeyBuilder},
90+
};
91+
8392
use crate::prelude::*;
8493

8594
/// Tag for the hash function used when signing an [`InvoiceRequest`]'s merkle root.
@@ -660,8 +669,6 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { (
660669
/// See [`InvoiceRequest::respond_with_no_std`] for further details where the aforementioned
661670
/// creation time is used for the `created_at` parameter.
662671
///
663-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
664-
///
665672
/// [`Duration`]: core::time::Duration
666673
#[cfg(feature = "std")]
667674
pub fn respond_with(
@@ -695,8 +702,6 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { (
695702
/// If the originating [`Offer`] was created using [`OfferBuilder::deriving_signing_pubkey`],
696703
/// then use [`InvoiceRequest::verify`] and [`VerifiedInvoiceRequest`] methods instead.
697704
///
698-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
699-
///
700705
/// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
701706
/// [`OfferBuilder::deriving_signing_pubkey`]: crate::offers::offer::OfferBuilder::deriving_signing_pubkey
702707
pub fn respond_with_no_std(
@@ -717,24 +722,45 @@ macro_rules! invoice_request_verify_method { ($self: ident, $self_type: ty) => {
717722
/// if they could be extracted from the metadata.
718723
///
719724
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
720-
pub fn verify<T: secp256k1::Signing>(
721-
$self: $self_type, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
725+
pub fn verify<
726+
#[cfg(not(c_bindings))]
727+
T: secp256k1::Signing
728+
>(
729+
$self: $self_type, key: &ExpandedKey,
730+
#[cfg(not(c_bindings))]
731+
secp_ctx: &Secp256k1<T>,
732+
#[cfg(c_bindings)]
733+
secp_ctx: &Secp256k1<secp256k1::All>,
722734
) -> Result<VerifiedInvoiceRequest, ()> {
723735
let keys = $self.contents.inner.offer.verify(&$self.bytes, key, secp_ctx)?;
724736
Ok(VerifiedInvoiceRequest {
737+
#[cfg(not(c_bindings))]
725738
inner: $self,
739+
#[cfg(c_bindings)]
740+
inner: $self.clone(),
726741
keys,
727742
})
728743
}
729744

730745
} }
731746

747+
#[cfg(not(c_bindings))]
732748
impl InvoiceRequest {
733749
offer_accessors!(self, self.contents.inner.offer);
734750
invoice_request_accessors!(self, self.contents);
735751
invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self, InvoiceBuilder<ExplicitSigningPubkey>);
736752
invoice_request_verify_method!(self, Self);
753+
}
737754

755+
#[cfg(c_bindings)]
756+
impl InvoiceRequest {
757+
offer_accessors!(self, self.contents.inner.offer);
758+
invoice_request_accessors!(self, self.contents);
759+
invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self, InvoiceWithExplicitSigningPubkeyBuilder);
760+
invoice_request_verify_method!(self, &Self);
761+
}
762+
763+
impl InvoiceRequest {
738764
/// Signature of the invoice request using [`payer_id`].
739765
///
740766
/// [`payer_id`]: Self::payer_id
@@ -761,8 +787,6 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
761787
///
762788
/// See [`InvoiceRequest::respond_with`] for further details.
763789
///
764-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
765-
///
766790
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
767791
#[cfg(feature = "std")]
768792
pub fn respond_using_derived_keys(
@@ -781,8 +805,6 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
781805
///
782806
/// See [`InvoiceRequest::respond_with_no_std`] for further details.
783807
///
784-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
785-
///
786808
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
787809
pub fn respond_using_derived_keys_no_std(
788810
&$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
@@ -806,8 +828,14 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
806828
impl VerifiedInvoiceRequest {
807829
offer_accessors!(self, self.inner.contents.inner.offer);
808830
invoice_request_accessors!(self, self.inner.contents);
831+
#[cfg(not(c_bindings))]
809832
invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self.inner, InvoiceBuilder<ExplicitSigningPubkey>);
833+
#[cfg(c_bindings)]
834+
invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self.inner, InvoiceWithExplicitSigningPubkeyBuilder);
835+
#[cfg(not(c_bindings))]
810836
invoice_request_respond_with_derived_signing_pubkey_methods!(self, self.inner, InvoiceBuilder<DerivedSigningPubkey>);
837+
#[cfg(c_bindings)]
838+
invoice_request_respond_with_derived_signing_pubkey_methods!(self, self.inner, InvoiceWithDerivedSigningPubkeyBuilder);
811839
}
812840

813841
impl InvoiceRequestContents {

0 commit comments

Comments
 (0)