Skip to content

Commit af318b6

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 c7b877e commit af318b6

File tree

3 files changed

+170
-33
lines changed

3 files changed

+170
-33
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: 139 additions & 22 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.
@@ -118,6 +149,7 @@ impl PayerIdStrategy for ExplicitPayerId {}
118149
impl PayerIdStrategy for DerivedPayerId {}
119150

120151
macro_rules! invoice_request_explicit_payer_id_builder_methods { ($self: ident, $self_type: ty) => {
152+
#[cfg_attr(c_bindings, allow(dead_code))]
121153
pub(super) fn new(offer: &'a Offer, metadata: Vec<u8>, payer_id: PublicKey) -> Self {
122154
Self {
123155
offer,
@@ -128,6 +160,7 @@ macro_rules! invoice_request_explicit_payer_id_builder_methods { ($self: ident,
128160
}
129161
}
130162

163+
#[cfg_attr(c_bindings, allow(dead_code))]
131164
pub(super) fn deriving_metadata<ES: Deref>(
132165
offer: &'a Offer, payer_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES,
133166
payment_id: PaymentId,
@@ -154,10 +187,13 @@ macro_rules! invoice_request_explicit_payer_id_builder_methods { ($self: ident,
154187
}
155188
} }
156189

157-
macro_rules! invoice_request_derived_payer_id_builder_methods { ($self: ident, $self_type: ty) => {
190+
macro_rules! invoice_request_derived_payer_id_builder_methods { (
191+
$self: ident, $self_type: ty, $secp_context: ty
192+
) => {
193+
#[cfg_attr(c_bindings, allow(dead_code))]
158194
pub(super) fn deriving_payer_id<ES: Deref>(
159195
offer: &'a Offer, expanded_key: &ExpandedKey, entropy_source: ES,
160-
secp_ctx: &'b Secp256k1<T>, payment_id: PaymentId
196+
secp_ctx: &'b Secp256k1<$secp_context>, payment_id: PaymentId
161197
) -> Self where ES::Target: EntropySource {
162198
let nonce = Nonce::from_entropy_source(entropy_source);
163199
let payment_id = Some(payment_id);
@@ -175,6 +211,8 @@ macro_rules! invoice_request_derived_payer_id_builder_methods { ($self: ident, $
175211
/// Builds a signed [`InvoiceRequest`] after checking for valid semantics.
176212
pub fn build_and_sign($self: $self_type) -> Result<InvoiceRequest, Bolt12SemanticError> {
177213
let (unsigned_invoice_request, keys, secp_ctx) = $self.build_with_checks()?;
214+
#[cfg(c_bindings)]
215+
let mut unsigned_invoice_request = unsigned_invoice_request;
178216
debug_assert!(keys.is_some());
179217

180218
let secp_ctx = secp_ctx.unwrap();
@@ -189,8 +227,9 @@ macro_rules! invoice_request_derived_payer_id_builder_methods { ($self: ident, $
189227
} }
190228

191229
macro_rules! invoice_request_builder_methods { (
192-
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr
230+
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr, $secp_context: ty $(, $self_mut: tt)?
193231
) => {
232+
#[cfg_attr(c_bindings, allow(dead_code))]
194233
fn create_contents(offer: &Offer, metadata: Metadata) -> InvoiceRequestContentsWithoutPayerId {
195234
let offer = offer.contents.clone();
196235
InvoiceRequestContentsWithoutPayerId {
@@ -213,7 +252,7 @@ macro_rules! invoice_request_builder_methods { (
213252
/// offer.
214253
///
215254
/// Successive calls to this method will override the previous setting.
216-
pub(crate) fn chain_hash(mut $self: $self_type, chain: ChainHash) -> Result<$return_type, Bolt12SemanticError> {
255+
pub(crate) fn chain_hash($($self_mut)* $self: $self_type, chain: ChainHash) -> Result<$return_type, Bolt12SemanticError> {
217256
if !$self.offer.supports_chain(chain) {
218257
return Err(Bolt12SemanticError::UnsupportedChain);
219258
}
@@ -228,7 +267,7 @@ macro_rules! invoice_request_builder_methods { (
228267
/// Successive calls to this method will override the previous setting.
229268
///
230269
/// [`quantity`]: Self::quantity
231-
pub fn amount_msats(mut $self: $self_type, amount_msats: u64) -> Result<$return_type, Bolt12SemanticError> {
270+
pub fn amount_msats($($self_mut)* $self: $self_type, amount_msats: u64) -> Result<$return_type, Bolt12SemanticError> {
232271
$self.invoice_request.offer.check_amount_msats_for_quantity(
233272
Some(amount_msats), $self.invoice_request.quantity
234273
)?;
@@ -240,7 +279,7 @@ macro_rules! invoice_request_builder_methods { (
240279
/// does not conform to [`Offer::is_valid_quantity`].
241280
///
242281
/// Successive calls to this method will override the previous setting.
243-
pub fn quantity(mut $self: $self_type, quantity: u64) -> Result<$return_type, Bolt12SemanticError> {
282+
pub fn quantity($($self_mut)* $self: $self_type, quantity: u64) -> Result<$return_type, Bolt12SemanticError> {
244283
$self.invoice_request.offer.check_quantity(Some(quantity))?;
245284
$self.invoice_request.quantity = Some(quantity);
246285
Ok($return_value)
@@ -249,13 +288,13 @@ macro_rules! invoice_request_builder_methods { (
249288
/// Sets the [`InvoiceRequest::payer_note`].
250289
///
251290
/// Successive calls to this method will override the previous setting.
252-
pub fn payer_note(mut $self: $self_type, payer_note: String) -> $return_type {
291+
pub fn payer_note($($self_mut)* $self: $self_type, payer_note: String) -> $return_type {
253292
$self.invoice_request.payer_note = Some(payer_note);
254293
$return_value
255294
}
256295

257-
fn build_with_checks(mut $self: $self_type) -> Result<
258-
(UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<T>>),
296+
fn build_with_checks($($self_mut)* $self: $self_type) -> Result<
297+
(UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<$secp_context>>),
259298
Bolt12SemanticError
260299
> {
261300
#[cfg(feature = "std")] {
@@ -285,8 +324,8 @@ macro_rules! invoice_request_builder_methods { (
285324
Ok($self.build_without_checks())
286325
}
287326

288-
fn build_without_checks(mut $self: $self_type) ->
289-
(UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<T>>)
327+
fn build_without_checks($($self_mut)* $self: $self_type) ->
328+
(UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<$secp_context>>)
290329
{
291330
// Create the metadata for stateless verification of a Bolt12Invoice.
292331
let mut keys = None;
@@ -317,7 +356,10 @@ macro_rules! invoice_request_builder_methods { (
317356
let payer_id = $self.payer_id.unwrap();
318357

319358
let invoice_request = InvoiceRequestContents {
359+
#[cfg(not(c_bindings))]
320360
inner: $self.invoice_request,
361+
#[cfg(c_bindings)]
362+
inner: $self.invoice_request.clone(),
321363
payer_id,
322364
};
323365
let unsigned_invoice_request = UnsignedInvoiceRequest::new($self.offer, invoice_request);
@@ -328,29 +370,34 @@ macro_rules! invoice_request_builder_methods { (
328370

329371
#[cfg(test)]
330372
macro_rules! invoice_request_builder_test_methods { (
331-
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr
373+
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr $(, $self_mut: tt)?
332374
) => {
333-
fn chain_unchecked(mut $self: $self_type, network: Network) -> $return_type {
375+
#[cfg_attr(c_bindings, allow(dead_code))]
376+
fn chain_unchecked($($self_mut)* $self: $self_type, network: Network) -> $return_type {
334377
let chain = ChainHash::using_genesis_block(network);
335378
$self.invoice_request.chain = Some(chain);
336379
$return_value
337380
}
338381

339-
fn amount_msats_unchecked(mut $self: $self_type, amount_msats: u64) -> $return_type {
382+
#[cfg_attr(c_bindings, allow(dead_code))]
383+
fn amount_msats_unchecked($($self_mut)* $self: $self_type, amount_msats: u64) -> $return_type {
340384
$self.invoice_request.amount_msats = Some(amount_msats);
341385
$return_value
342386
}
343387

344-
fn features_unchecked(mut $self: $self_type, features: InvoiceRequestFeatures) -> $return_type {
388+
#[cfg_attr(c_bindings, allow(dead_code))]
389+
fn features_unchecked($($self_mut)* $self: $self_type, features: InvoiceRequestFeatures) -> $return_type {
345390
$self.invoice_request.features = features;
346391
$return_value
347392
}
348393

349-
fn quantity_unchecked(mut $self: $self_type, quantity: u64) -> $return_type {
394+
#[cfg_attr(c_bindings, allow(dead_code))]
395+
fn quantity_unchecked($($self_mut)* $self: $self_type, quantity: u64) -> $return_type {
350396
$self.invoice_request.quantity = Some(quantity);
351397
$return_value
352398
}
353399

400+
#[cfg_attr(c_bindings, allow(dead_code))]
354401
pub(super) fn build_unchecked($self: $self_type) -> UnsignedInvoiceRequest {
355402
$self.build_without_checks().0
356403
}
@@ -361,14 +408,68 @@ impl<'a, 'b, T: secp256k1::Signing> InvoiceRequestBuilder<'a, 'b, ExplicitPayerI
361408
}
362409

363410
impl<'a, 'b, T: secp256k1::Signing> InvoiceRequestBuilder<'a, 'b, DerivedPayerId, T> {
364-
invoice_request_derived_payer_id_builder_methods!(self, Self);
411+
invoice_request_derived_payer_id_builder_methods!(self, Self, T);
365412
}
366413

367414
impl<'a, 'b, P: PayerIdStrategy, T: secp256k1::Signing> InvoiceRequestBuilder<'a, 'b, P, T> {
368-
invoice_request_builder_methods!(self, Self, Self, self);
415+
invoice_request_builder_methods!(self, Self, Self, self, T, mut);
369416

370417
#[cfg(test)]
371-
invoice_request_builder_test_methods!(self, Self, Self, self);
418+
invoice_request_builder_test_methods!(self, Self, Self, self, mut);
419+
}
420+
421+
#[cfg(all(c_bindings, not(test)))]
422+
impl<'a, 'b> InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b> {
423+
invoice_request_explicit_payer_id_builder_methods!(self, &mut Self);
424+
invoice_request_builder_methods!(self, &mut Self, (), (), secp256k1::All);
425+
}
426+
427+
#[cfg(all(c_bindings, test))]
428+
impl<'a, 'b> InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b> {
429+
invoice_request_explicit_payer_id_builder_methods!(self, &mut Self);
430+
invoice_request_builder_methods!(self, &mut Self, &mut Self, self, secp256k1::All);
431+
invoice_request_builder_test_methods!(self, &mut Self, &mut Self, self);
432+
}
433+
434+
#[cfg(all(c_bindings, not(test)))]
435+
impl<'a, 'b> InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b> {
436+
invoice_request_derived_payer_id_builder_methods!(self, &mut Self, secp256k1::All);
437+
invoice_request_builder_methods!(self, &mut Self, (), (), secp256k1::All);
438+
}
439+
440+
#[cfg(all(c_bindings, test))]
441+
impl<'a, 'b> InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b> {
442+
invoice_request_derived_payer_id_builder_methods!(self, &mut Self, secp256k1::All);
443+
invoice_request_builder_methods!(self, &mut Self, &mut Self, self, secp256k1::All);
444+
invoice_request_builder_test_methods!(self, &mut Self, &mut Self, self);
445+
}
446+
447+
#[cfg(c_bindings)]
448+
impl<'a, 'b> From<InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b>>
449+
for InvoiceRequestBuilder<'a, 'b, ExplicitPayerId, secp256k1::All> {
450+
fn from(builder: InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b>) -> Self {
451+
let InvoiceRequestWithExplicitPayerIdBuilder {
452+
offer, invoice_request, payer_id, payer_id_strategy, secp_ctx,
453+
} = builder;
454+
455+
Self {
456+
offer, invoice_request, payer_id, payer_id_strategy, secp_ctx,
457+
}
458+
}
459+
}
460+
461+
#[cfg(c_bindings)]
462+
impl<'a, 'b> From<InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b>>
463+
for InvoiceRequestBuilder<'a, 'b, DerivedPayerId, secp256k1::All> {
464+
fn from(builder: InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b>) -> Self {
465+
let InvoiceRequestWithDerivedPayerIdBuilder {
466+
offer, invoice_request, payer_id, payer_id_strategy, secp_ctx,
467+
} = builder;
468+
469+
Self {
470+
offer, invoice_request, payer_id, payer_id_strategy, secp_ctx,
471+
}
472+
}
372473
}
373474

374475
/// A semantically valid [`InvoiceRequest`] that hasn't been signed.
@@ -406,13 +507,15 @@ impl UnsignedInvoiceRequest {
406507
}
407508
}
408509

409-
macro_rules! unsigned_invoice_request_sign_method { ($self: ident, $self_type: ty) => {
510+
macro_rules! unsigned_invoice_request_sign_method { (
511+
$self: ident, $self_type: ty $(, $self_mut: tt)?
512+
) => {
410513
/// Signs the [`TaggedHash`] of the invoice request using the given function.
411514
///
412515
/// Note: The hash computation may have included unknown, odd TLV records.
413516
///
414517
/// This is not exported to bindings users as functions are not yet mapped.
415-
pub fn sign<F, E>(mut $self: $self_type, sign: F) -> Result<InvoiceRequest, SignError<E>>
518+
pub fn sign<F, E>($($self_mut)* $self: $self_type, sign: F) -> Result<InvoiceRequest, SignError<E>>
416519
where
417520
F: FnOnce(&Self) -> Result<Signature, E>
418521
{
@@ -426,15 +529,27 @@ macro_rules! unsigned_invoice_request_sign_method { ($self: ident, $self_type: t
426529
signature_tlv_stream.write(&mut $self.bytes).unwrap();
427530

428531
Ok(InvoiceRequest {
532+
#[cfg(not(c_bindings))]
429533
bytes: $self.bytes,
534+
#[cfg(c_bindings)]
535+
bytes: $self.bytes.clone(),
536+
#[cfg(not(c_bindings))]
430537
contents: $self.contents,
538+
#[cfg(c_bindings)]
539+
contents: $self.contents.clone(),
431540
signature,
432541
})
433542
}
434543
} }
435544

545+
#[cfg(not(c_bindings))]
546+
impl UnsignedInvoiceRequest {
547+
unsigned_invoice_request_sign_method!(self, Self, mut);
548+
}
549+
550+
#[cfg(c_bindings)]
436551
impl UnsignedInvoiceRequest {
437-
unsigned_invoice_request_sign_method!(self, Self);
552+
unsigned_invoice_request_sign_method!(self, &mut Self);
438553
}
439554

440555
impl AsRef<TaggedHash> for UnsignedInvoiceRequest {
@@ -984,6 +1099,8 @@ mod tests {
9841099
.build().unwrap()
9851100
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
9861101
.build().unwrap();
1102+
#[cfg(c_bindings)]
1103+
let mut unsigned_invoice_request = unsigned_invoice_request;
9871104

9881105
let mut buffer = Vec::new();
9891106
unsigned_invoice_request.write(&mut buffer).unwrap();

0 commit comments

Comments
 (0)