Skip to content

Commit 94e988d

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 27b178e commit 94e988d

File tree

4 files changed

+173
-22
lines changed

4 files changed

+173
-22
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 6 additions & 1 deletion
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

Lines changed: 111 additions & 9 deletions
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

Lines changed: 39 additions & 11 deletions
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.
@@ -662,8 +671,6 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { (
662671
/// See [`InvoiceRequest::respond_with_no_std`] for further details where the aforementioned
663672
/// creation time is used for the `created_at` parameter.
664673
///
665-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
666-
///
667674
/// [`Duration`]: core::time::Duration
668675
#[cfg(feature = "std")]
669676
pub fn respond_with(
@@ -697,8 +704,6 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { (
697704
/// If the originating [`Offer`] was created using [`OfferBuilder::deriving_signing_pubkey`],
698705
/// then use [`InvoiceRequest::verify`] and [`VerifiedInvoiceRequest`] methods instead.
699706
///
700-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
701-
///
702707
/// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
703708
/// [`OfferBuilder::deriving_signing_pubkey`]: crate::offers::offer::OfferBuilder::deriving_signing_pubkey
704709
pub fn respond_with_no_std(
@@ -719,24 +724,45 @@ macro_rules! invoice_request_verify_method { ($self: ident, $self_type: ty) => {
719724
/// if they could be extracted from the metadata.
720725
///
721726
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
722-
pub fn verify<T: secp256k1::Signing>(
723-
$self: $self_type, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
727+
pub fn verify<
728+
#[cfg(not(c_bindings))]
729+
T: secp256k1::Signing
730+
>(
731+
$self: $self_type, key: &ExpandedKey,
732+
#[cfg(not(c_bindings))]
733+
secp_ctx: &Secp256k1<T>,
734+
#[cfg(c_bindings)]
735+
secp_ctx: &Secp256k1<secp256k1::All>,
724736
) -> Result<VerifiedInvoiceRequest, ()> {
725737
let keys = $self.contents.inner.offer.verify(&$self.bytes, key, secp_ctx)?;
726738
Ok(VerifiedInvoiceRequest {
739+
#[cfg(not(c_bindings))]
727740
inner: $self,
741+
#[cfg(c_bindings)]
742+
inner: $self.clone(),
728743
keys,
729744
})
730745
}
731746

732747
} }
733748

749+
#[cfg(not(c_bindings))]
734750
impl InvoiceRequest {
735751
offer_accessors!(self, self.contents.inner.offer);
736752
invoice_request_accessors!(self, self.contents);
737753
invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self, InvoiceBuilder<ExplicitSigningPubkey>);
738754
invoice_request_verify_method!(self, Self);
755+
}
739756

757+
#[cfg(c_bindings)]
758+
impl InvoiceRequest {
759+
offer_accessors!(self, self.contents.inner.offer);
760+
invoice_request_accessors!(self, self.contents);
761+
invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self, InvoiceWithExplicitSigningPubkeyBuilder);
762+
invoice_request_verify_method!(self, &Self);
763+
}
764+
765+
impl InvoiceRequest {
740766
/// Signature of the invoice request using [`payer_id`].
741767
///
742768
/// [`payer_id`]: Self::payer_id
@@ -763,8 +789,6 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
763789
///
764790
/// See [`InvoiceRequest::respond_with`] for further details.
765791
///
766-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
767-
///
768792
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
769793
#[cfg(feature = "std")]
770794
pub fn respond_using_derived_keys(
@@ -783,8 +807,6 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
783807
///
784808
/// See [`InvoiceRequest::respond_with_no_std`] for further details.
785809
///
786-
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
787-
///
788810
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
789811
pub fn respond_using_derived_keys_no_std(
790812
&$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
@@ -808,8 +830,14 @@ macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
808830
impl VerifiedInvoiceRequest {
809831
offer_accessors!(self, self.inner.contents.inner.offer);
810832
invoice_request_accessors!(self, self.inner.contents);
833+
#[cfg(not(c_bindings))]
811834
invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self.inner, InvoiceBuilder<ExplicitSigningPubkey>);
835+
#[cfg(c_bindings)]
836+
invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self.inner, InvoiceWithExplicitSigningPubkeyBuilder);
837+
#[cfg(not(c_bindings))]
812838
invoice_request_respond_with_derived_signing_pubkey_methods!(self, self.inner, InvoiceBuilder<DerivedSigningPubkey>);
839+
#[cfg(c_bindings)]
840+
invoice_request_respond_with_derived_signing_pubkey_methods!(self, self.inner, InvoiceWithDerivedSigningPubkeyBuilder);
813841
}
814842

815843
impl InvoiceRequestContents {

0 commit comments

Comments
 (0)