//!
//! use bitcoin::network::constants::Network;
//! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
-//! use core::convert::Infallible;
//! use lightning::ln::features::OfferFeatures;
+//! use lightning::offers::invoice_request::UnsignedInvoiceRequest;
//! use lightning::offers::offer::Offer;
//! use lightning::util::ser::Writeable;
//!
//! let pubkey = PublicKey::from(keys);
//! let mut buffer = Vec::new();
//!
+//! # use lightning::offers::invoice_request::{ExplicitPayerId, InvoiceRequestBuilder};
+//! # <InvoiceRequestBuilder<ExplicitPayerId, _>>::from(
//! "lno1qcp4256ypq"
//! .parse::<Offer>()?
//! .request_invoice(vec![42; 64], pubkey)?
+//! # )
//! .chain(Network::Testnet)?
//! .amount_msats(1000)?
//! .quantity(5)?
//! .payer_note("foo".to_string())
//! .build()?
-//! .sign::<_, Infallible>(
-//! |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
+//! .sign(|message: &UnsignedInvoiceRequest|
+//! Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
//! )
//! .expect("failed verifying signature")
//! .write(&mut buffer)
use bitcoin::network::constants::Network;
use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, self};
use bitcoin::secp256k1::schnorr::Signature;
-use core::convert::{AsRef, Infallible, TryFrom};
use core::ops::Deref;
use crate::sign::EntropySource;
use crate::io;
use crate::ln::features::InvoiceRequestFeatures;
use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce};
use crate::ln::msgs::DecodeError;
-use crate::offers::invoice::{BlindedPayInfo, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder};
-use crate::offers::merkle::{SignError, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, self};
+use crate::offers::invoice::BlindedPayInfo;
+use crate::offers::merkle::{SignError, SignFn, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, self};
use crate::offers::offer::{Offer, OfferContents, OfferTlvStream, OfferTlvStreamRef};
use crate::offers::parse::{Bolt12ParseError, ParsedMessage, Bolt12SemanticError};
use crate::offers::payer::{PayerContents, PayerTlvStream, PayerTlvStreamRef};
use crate::util::ser::{HighZeroBytesDroppedBigSize, SeekReadable, WithoutLength, Writeable, Writer};
use crate::util::string::PrintableString;
+#[cfg(not(c_bindings))]
+use {
+ crate::offers::invoice::{DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder},
+};
+#[cfg(c_bindings)]
+use {
+ crate::offers::invoice::{InvoiceWithDerivedSigningPubkeyBuilder, InvoiceWithExplicitSigningPubkeyBuilder},
+};
+
+#[allow(unused_imports)]
use crate::prelude::*;
/// Tag for the hash function used when signing an [`InvoiceRequest`]'s merkle root.
secp_ctx: Option<&'b Secp256k1<T>>,
}
+/// Builds an [`InvoiceRequest`] from an [`Offer`] for the "offer to be paid" flow.
+///
+/// See [module-level documentation] for usage.
+///
+/// [module-level documentation]: self
+#[cfg(c_bindings)]
+pub struct InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b> {
+ offer: &'a Offer,
+ invoice_request: InvoiceRequestContentsWithoutPayerId,
+ payer_id: Option<PublicKey>,
+ payer_id_strategy: core::marker::PhantomData<ExplicitPayerId>,
+ secp_ctx: Option<&'b Secp256k1<secp256k1::All>>,
+}
+
+/// Builds an [`InvoiceRequest`] from an [`Offer`] for the "offer to be paid" flow.
+///
+/// See [module-level documentation] for usage.
+///
+/// [module-level documentation]: self
+#[cfg(c_bindings)]
+pub struct InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b> {
+ offer: &'a Offer,
+ invoice_request: InvoiceRequestContentsWithoutPayerId,
+ payer_id: Option<PublicKey>,
+ payer_id_strategy: core::marker::PhantomData<DerivedPayerId>,
+ secp_ctx: Option<&'b Secp256k1<secp256k1::All>>,
+}
+
/// Indicates how [`InvoiceRequest::payer_id`] will be set.
///
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
impl PayerIdStrategy for DerivedPayerId {}
macro_rules! invoice_request_explicit_payer_id_builder_methods { ($self: ident, $self_type: ty) => {
+ #[cfg_attr(c_bindings, allow(dead_code))]
pub(super) fn new(offer: &'a Offer, metadata: Vec<u8>, payer_id: PublicKey) -> Self {
Self {
offer,
}
}
+ #[cfg_attr(c_bindings, allow(dead_code))]
pub(super) fn deriving_metadata<ES: Deref>(
offer: &'a Offer, payer_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES,
payment_id: PaymentId,
}
} }
-macro_rules! invoice_request_derived_payer_id_builder_methods { ($self: ident, $self_type: ty) => {
+macro_rules! invoice_request_derived_payer_id_builder_methods { (
+ $self: ident, $self_type: ty, $secp_context: ty
+) => {
+ #[cfg_attr(c_bindings, allow(dead_code))]
pub(super) fn deriving_payer_id<ES: Deref>(
offer: &'a Offer, expanded_key: &ExpandedKey, entropy_source: ES,
- secp_ctx: &'b Secp256k1<T>, payment_id: PaymentId
+ secp_ctx: &'b Secp256k1<$secp_context>, payment_id: PaymentId
) -> Self where ES::Target: EntropySource {
let nonce = Nonce::from_entropy_source(entropy_source);
let payment_id = Some(payment_id);
/// Builds a signed [`InvoiceRequest`] after checking for valid semantics.
pub fn build_and_sign($self: $self_type) -> Result<InvoiceRequest, Bolt12SemanticError> {
let (unsigned_invoice_request, keys, secp_ctx) = $self.build_with_checks()?;
+ #[cfg(c_bindings)]
+ let mut unsigned_invoice_request = unsigned_invoice_request;
debug_assert!(keys.is_some());
let secp_ctx = secp_ctx.unwrap();
let keys = keys.unwrap();
let invoice_request = unsigned_invoice_request
- .sign::<_, Infallible>(
- |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
+ .sign(|message: &UnsignedInvoiceRequest|
+ Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
)
.unwrap();
Ok(invoice_request)
} }
macro_rules! invoice_request_builder_methods { (
- $self: ident, $self_type: ty, $return_type: ty, $return_value: expr
+ $self: ident, $self_type: ty, $return_type: ty, $return_value: expr, $secp_context: ty $(, $self_mut: tt)?
) => {
+ #[cfg_attr(c_bindings, allow(dead_code))]
fn create_contents(offer: &Offer, metadata: Metadata) -> InvoiceRequestContentsWithoutPayerId {
let offer = offer.contents.clone();
InvoiceRequestContentsWithoutPayerId {
/// offer.
///
/// Successive calls to this method will override the previous setting.
- pub(crate) fn chain_hash(mut $self: $self_type, chain: ChainHash) -> Result<$return_type, Bolt12SemanticError> {
+ pub(crate) fn chain_hash($($self_mut)* $self: $self_type, chain: ChainHash) -> Result<$return_type, Bolt12SemanticError> {
if !$self.offer.supports_chain(chain) {
return Err(Bolt12SemanticError::UnsupportedChain);
}
/// Successive calls to this method will override the previous setting.
///
/// [`quantity`]: Self::quantity
- pub fn amount_msats(mut $self: $self_type, amount_msats: u64) -> Result<$return_type, Bolt12SemanticError> {
+ pub fn amount_msats($($self_mut)* $self: $self_type, amount_msats: u64) -> Result<$return_type, Bolt12SemanticError> {
$self.invoice_request.offer.check_amount_msats_for_quantity(
Some(amount_msats), $self.invoice_request.quantity
)?;
/// does not conform to [`Offer::is_valid_quantity`].
///
/// Successive calls to this method will override the previous setting.
- pub fn quantity(mut $self: $self_type, quantity: u64) -> Result<$return_type, Bolt12SemanticError> {
+ pub fn quantity($($self_mut)* $self: $self_type, quantity: u64) -> Result<$return_type, Bolt12SemanticError> {
$self.invoice_request.offer.check_quantity(Some(quantity))?;
$self.invoice_request.quantity = Some(quantity);
Ok($return_value)
/// Sets the [`InvoiceRequest::payer_note`].
///
/// Successive calls to this method will override the previous setting.
- pub fn payer_note(mut $self: $self_type, payer_note: String) -> $return_type {
+ pub fn payer_note($($self_mut)* $self: $self_type, payer_note: String) -> $return_type {
$self.invoice_request.payer_note = Some(payer_note);
$return_value
}
- fn build_with_checks(mut $self: $self_type) -> Result<
- (UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<T>>),
+ fn build_with_checks($($self_mut)* $self: $self_type) -> Result<
+ (UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<$secp_context>>),
Bolt12SemanticError
> {
#[cfg(feature = "std")] {
Ok($self.build_without_checks())
}
- fn build_without_checks(mut $self: $self_type) ->
- (UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<T>>)
+ fn build_without_checks($($self_mut)* $self: $self_type) ->
+ (UnsignedInvoiceRequest, Option<KeyPair>, Option<&'b Secp256k1<$secp_context>>)
{
// Create the metadata for stateless verification of a Bolt12Invoice.
let mut keys = None;
let payer_id = $self.payer_id.unwrap();
let invoice_request = InvoiceRequestContents {
+ #[cfg(not(c_bindings))]
inner: $self.invoice_request,
+ #[cfg(c_bindings)]
+ inner: $self.invoice_request.clone(),
payer_id,
};
let unsigned_invoice_request = UnsignedInvoiceRequest::new($self.offer, invoice_request);
#[cfg(test)]
macro_rules! invoice_request_builder_test_methods { (
- $self: ident, $self_type: ty, $return_type: ty, $return_value: expr
+ $self: ident, $self_type: ty, $return_type: ty, $return_value: expr $(, $self_mut: tt)?
) => {
- fn chain_unchecked(mut $self: $self_type, network: Network) -> $return_type {
+ #[cfg_attr(c_bindings, allow(dead_code))]
+ fn chain_unchecked($($self_mut)* $self: $self_type, network: Network) -> $return_type {
let chain = ChainHash::using_genesis_block(network);
$self.invoice_request.chain = Some(chain);
$return_value
}
- fn amount_msats_unchecked(mut $self: $self_type, amount_msats: u64) -> $return_type {
+ #[cfg_attr(c_bindings, allow(dead_code))]
+ fn amount_msats_unchecked($($self_mut)* $self: $self_type, amount_msats: u64) -> $return_type {
$self.invoice_request.amount_msats = Some(amount_msats);
$return_value
}
- fn features_unchecked(mut $self: $self_type, features: InvoiceRequestFeatures) -> $return_type {
+ #[cfg_attr(c_bindings, allow(dead_code))]
+ fn features_unchecked($($self_mut)* $self: $self_type, features: InvoiceRequestFeatures) -> $return_type {
$self.invoice_request.features = features;
$return_value
}
- fn quantity_unchecked(mut $self: $self_type, quantity: u64) -> $return_type {
+ #[cfg_attr(c_bindings, allow(dead_code))]
+ fn quantity_unchecked($($self_mut)* $self: $self_type, quantity: u64) -> $return_type {
$self.invoice_request.quantity = Some(quantity);
$return_value
}
+ #[cfg_attr(c_bindings, allow(dead_code))]
pub(super) fn build_unchecked($self: $self_type) -> UnsignedInvoiceRequest {
$self.build_without_checks().0
}
}
impl<'a, 'b, T: secp256k1::Signing> InvoiceRequestBuilder<'a, 'b, DerivedPayerId, T> {
- invoice_request_derived_payer_id_builder_methods!(self, Self);
+ invoice_request_derived_payer_id_builder_methods!(self, Self, T);
}
impl<'a, 'b, P: PayerIdStrategy, T: secp256k1::Signing> InvoiceRequestBuilder<'a, 'b, P, T> {
- invoice_request_builder_methods!(self, Self, Self, self);
+ invoice_request_builder_methods!(self, Self, Self, self, T, mut);
#[cfg(test)]
- invoice_request_builder_test_methods!(self, Self, Self, self);
+ invoice_request_builder_test_methods!(self, Self, Self, self, mut);
+}
+
+#[cfg(all(c_bindings, not(test)))]
+impl<'a, 'b> InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b> {
+ invoice_request_explicit_payer_id_builder_methods!(self, &mut Self);
+ invoice_request_builder_methods!(self, &mut Self, (), (), secp256k1::All);
+}
+
+#[cfg(all(c_bindings, test))]
+impl<'a, 'b> InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b> {
+ invoice_request_explicit_payer_id_builder_methods!(self, &mut Self);
+ invoice_request_builder_methods!(self, &mut Self, &mut Self, self, secp256k1::All);
+ invoice_request_builder_test_methods!(self, &mut Self, &mut Self, self);
+}
+
+#[cfg(all(c_bindings, not(test)))]
+impl<'a, 'b> InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b> {
+ invoice_request_derived_payer_id_builder_methods!(self, &mut Self, secp256k1::All);
+ invoice_request_builder_methods!(self, &mut Self, (), (), secp256k1::All);
+}
+
+#[cfg(all(c_bindings, test))]
+impl<'a, 'b> InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b> {
+ invoice_request_derived_payer_id_builder_methods!(self, &mut Self, secp256k1::All);
+ invoice_request_builder_methods!(self, &mut Self, &mut Self, self, secp256k1::All);
+ invoice_request_builder_test_methods!(self, &mut Self, &mut Self, self);
+}
+
+#[cfg(c_bindings)]
+impl<'a, 'b> From<InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b>>
+for InvoiceRequestBuilder<'a, 'b, ExplicitPayerId, secp256k1::All> {
+ fn from(builder: InvoiceRequestWithExplicitPayerIdBuilder<'a, 'b>) -> Self {
+ let InvoiceRequestWithExplicitPayerIdBuilder {
+ offer, invoice_request, payer_id, payer_id_strategy, secp_ctx,
+ } = builder;
+
+ Self {
+ offer, invoice_request, payer_id, payer_id_strategy, secp_ctx,
+ }
+ }
+}
+
+#[cfg(c_bindings)]
+impl<'a, 'b> From<InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b>>
+for InvoiceRequestBuilder<'a, 'b, DerivedPayerId, secp256k1::All> {
+ fn from(builder: InvoiceRequestWithDerivedPayerIdBuilder<'a, 'b>) -> Self {
+ let InvoiceRequestWithDerivedPayerIdBuilder {
+ offer, invoice_request, payer_id, payer_id_strategy, secp_ctx,
+ } = builder;
+
+ Self {
+ offer, invoice_request, payer_id, payer_id_strategy, secp_ctx,
+ }
+ }
}
/// A semantically valid [`InvoiceRequest`] that hasn't been signed.
tagged_hash: TaggedHash,
}
+/// A function for signing an [`UnsignedInvoiceRequest`].
+pub trait SignInvoiceRequestFn {
+ /// Signs a [`TaggedHash`] computed over the merkle root of `message`'s TLV stream.
+ fn sign_invoice_request(&self, message: &UnsignedInvoiceRequest) -> Result<Signature, ()>;
+}
+
+impl<F> SignInvoiceRequestFn for F
+where
+ F: Fn(&UnsignedInvoiceRequest) -> Result<Signature, ()>,
+{
+ fn sign_invoice_request(&self, message: &UnsignedInvoiceRequest) -> Result<Signature, ()> {
+ self(message)
+ }
+}
+
+impl<F> SignFn<UnsignedInvoiceRequest> for F
+where
+ F: SignInvoiceRequestFn,
+{
+ fn sign(&self, message: &UnsignedInvoiceRequest) -> Result<Signature, ()> {
+ self.sign_invoice_request(message)
+ }
+}
+
impl UnsignedInvoiceRequest {
fn new(offer: &Offer, contents: InvoiceRequestContents) -> Self {
// Use the offer bytes instead of the offer TLV stream as the offer may have contained
}
}
-macro_rules! unsigned_invoice_request_sign_method { ($self: ident, $self_type: ty) => {
+macro_rules! unsigned_invoice_request_sign_method { (
+ $self: ident, $self_type: ty $(, $self_mut: tt)?
+) => {
/// Signs the [`TaggedHash`] of the invoice request using the given function.
///
/// Note: The hash computation may have included unknown, odd TLV records.
- ///
- /// This is not exported to bindings users as functions are not yet mapped.
- pub fn sign<F, E>(mut $self: $self_type, sign: F) -> Result<InvoiceRequest, SignError<E>>
- where
- F: FnOnce(&Self) -> Result<Signature, E>
- {
+ pub fn sign<F: SignInvoiceRequestFn>(
+ $($self_mut)* $self: $self_type, sign: F
+ ) -> Result<InvoiceRequest, SignError> {
let pubkey = $self.contents.payer_id;
let signature = merkle::sign_message(sign, &$self, pubkey)?;
signature_tlv_stream.write(&mut $self.bytes).unwrap();
Ok(InvoiceRequest {
+ #[cfg(not(c_bindings))]
bytes: $self.bytes,
+ #[cfg(c_bindings)]
+ bytes: $self.bytes.clone(),
+ #[cfg(not(c_bindings))]
contents: $self.contents,
+ #[cfg(c_bindings)]
+ contents: $self.contents.clone(),
signature,
})
}
} }
+#[cfg(not(c_bindings))]
+impl UnsignedInvoiceRequest {
+ unsigned_invoice_request_sign_method!(self, Self, mut);
+}
+
+#[cfg(c_bindings)]
impl UnsignedInvoiceRequest {
- unsigned_invoice_request_sign_method!(self, Self);
+ unsigned_invoice_request_sign_method!(self, &mut Self);
}
impl AsRef<TaggedHash> for UnsignedInvoiceRequest {
invoice_request_accessors!(self, self.contents);
}
-impl InvoiceRequest {
- offer_accessors!(self, self.contents.inner.offer);
- invoice_request_accessors!(self, self.contents);
-
- /// Signature of the invoice request using [`payer_id`].
- ///
- /// [`payer_id`]: Self::payer_id
- pub fn signature(&self) -> Signature {
- self.signature
- }
-
+macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { (
+ $self: ident, $contents: expr, $builder: ty
+) => {
/// Creates an [`InvoiceBuilder`] for the request with the given required fields and using the
/// [`Duration`] since [`std::time::SystemTime::UNIX_EPOCH`] as the creation time.
///
/// See [`InvoiceRequest::respond_with_no_std`] for further details where the aforementioned
/// creation time is used for the `created_at` parameter.
///
- /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
- ///
/// [`Duration`]: core::time::Duration
#[cfg(feature = "std")]
pub fn respond_with(
- &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash
- ) -> Result<InvoiceBuilder<ExplicitSigningPubkey>, Bolt12SemanticError> {
+ &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash
+ ) -> Result<$builder, Bolt12SemanticError> {
let created_at = std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
- self.respond_with_no_std(payment_paths, payment_hash, created_at)
+ $contents.respond_with_no_std(payment_paths, payment_hash, created_at)
}
/// Creates an [`InvoiceBuilder`] for the request with the given required fields.
/// If the originating [`Offer`] was created using [`OfferBuilder::deriving_signing_pubkey`],
/// then use [`InvoiceRequest::verify`] and [`VerifiedInvoiceRequest`] methods instead.
///
- /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
- ///
/// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
/// [`OfferBuilder::deriving_signing_pubkey`]: crate::offers::offer::OfferBuilder::deriving_signing_pubkey
pub fn respond_with_no_std(
- &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
+ &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
created_at: core::time::Duration
- ) -> Result<InvoiceBuilder<ExplicitSigningPubkey>, Bolt12SemanticError> {
- if self.invoice_request_features().requires_unknown_bits() {
+ ) -> Result<$builder, Bolt12SemanticError> {
+ if $contents.invoice_request_features().requires_unknown_bits() {
return Err(Bolt12SemanticError::UnknownRequiredFeatures);
}
- InvoiceBuilder::for_offer(self, payment_paths, created_at, payment_hash)
+ <$builder>::for_offer(&$contents, payment_paths, created_at, payment_hash)
}
+} }
+macro_rules! invoice_request_verify_method { ($self: ident, $self_type: ty) => {
/// Verifies that the request was for an offer created using the given key. Returns the verified
/// request which contains the derived keys needed to sign a [`Bolt12Invoice`] for the request
/// if they could be extracted from the metadata.
///
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
- pub fn verify<T: secp256k1::Signing>(
- self, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
+ pub fn verify<
+ #[cfg(not(c_bindings))]
+ T: secp256k1::Signing
+ >(
+ $self: $self_type, key: &ExpandedKey,
+ #[cfg(not(c_bindings))]
+ secp_ctx: &Secp256k1<T>,
+ #[cfg(c_bindings)]
+ secp_ctx: &Secp256k1<secp256k1::All>,
) -> Result<VerifiedInvoiceRequest, ()> {
- let keys = self.contents.inner.offer.verify(&self.bytes, key, secp_ctx)?;
+ let keys = $self.contents.inner.offer.verify(&$self.bytes, key, secp_ctx)?;
Ok(VerifiedInvoiceRequest {
- inner: self,
+ #[cfg(not(c_bindings))]
+ inner: $self,
+ #[cfg(c_bindings)]
+ inner: $self.clone(),
keys,
})
}
+} }
+
+#[cfg(not(c_bindings))]
+impl InvoiceRequest {
+ offer_accessors!(self, self.contents.inner.offer);
+ invoice_request_accessors!(self, self.contents);
+ invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self, InvoiceBuilder<ExplicitSigningPubkey>);
+ invoice_request_verify_method!(self, Self);
+}
+
+#[cfg(c_bindings)]
+impl InvoiceRequest {
+ offer_accessors!(self, self.contents.inner.offer);
+ invoice_request_accessors!(self, self.contents);
+ invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self, InvoiceWithExplicitSigningPubkeyBuilder);
+ invoice_request_verify_method!(self, &Self);
+}
+
+impl InvoiceRequest {
+ /// Signature of the invoice request using [`payer_id`].
+ ///
+ /// [`payer_id`]: Self::payer_id
+ pub fn signature(&self) -> Signature {
+ self.signature
+ }
+
pub(crate) fn as_tlv_stream(&self) -> FullInvoiceRequestTlvStreamRef {
let (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) =
self.contents.as_tlv_stream();
}
}
-impl VerifiedInvoiceRequest {
- offer_accessors!(self, self.inner.contents.inner.offer);
- invoice_request_accessors!(self, self.inner.contents);
-
- /// Creates an [`InvoiceBuilder`] for the request with the given required fields and using the
- /// [`Duration`] since [`std::time::SystemTime::UNIX_EPOCH`] as the creation time.
- ///
- /// See [`InvoiceRequest::respond_with_no_std`] for further details.
- ///
- /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
- ///
- /// [`Duration`]: core::time::Duration
- #[cfg(feature = "std")]
- pub fn respond_with(
- &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash
- ) -> Result<InvoiceBuilder<ExplicitSigningPubkey>, Bolt12SemanticError> {
- self.inner.respond_with(payment_paths, payment_hash)
- }
-
- /// Creates an [`InvoiceBuilder`] for the request with the given required fields.
- ///
- /// See [`InvoiceRequest::respond_with_no_std`] for further details.
- ///
- /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
- pub fn respond_with_no_std(
- &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
- created_at: core::time::Duration
- ) -> Result<InvoiceBuilder<ExplicitSigningPubkey>, Bolt12SemanticError> {
- self.inner.respond_with_no_std(payment_paths, payment_hash, created_at)
- }
-
+macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
+ $self: ident, $contents: expr, $builder: ty
+) => {
/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
/// derived signing keys from the originating [`Offer`] to sign the [`Bolt12Invoice`]. Must use
/// the same [`ExpandedKey`] as the one used to create the offer.
///
/// See [`InvoiceRequest::respond_with`] for further details.
///
- /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
- ///
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
#[cfg(feature = "std")]
pub fn respond_using_derived_keys(
- &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash
- ) -> Result<InvoiceBuilder<DerivedSigningPubkey>, Bolt12SemanticError> {
+ &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash
+ ) -> Result<$builder, Bolt12SemanticError> {
let created_at = std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
- self.respond_using_derived_keys_no_std(payment_paths, payment_hash, created_at)
+ $self.respond_using_derived_keys_no_std(payment_paths, payment_hash, created_at)
}
/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
///
/// See [`InvoiceRequest::respond_with_no_std`] for further details.
///
- /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
- ///
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
pub fn respond_using_derived_keys_no_std(
- &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
+ &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
created_at: core::time::Duration
- ) -> Result<InvoiceBuilder<DerivedSigningPubkey>, Bolt12SemanticError> {
- if self.inner.invoice_request_features().requires_unknown_bits() {
+ ) -> Result<$builder, Bolt12SemanticError> {
+ if $self.inner.invoice_request_features().requires_unknown_bits() {
return Err(Bolt12SemanticError::UnknownRequiredFeatures);
}
- let keys = match self.keys {
+ let keys = match $self.keys {
None => return Err(Bolt12SemanticError::InvalidMetadata),
Some(keys) => keys,
};
- InvoiceBuilder::for_offer_using_keys(
- &self.inner, payment_paths, created_at, payment_hash, keys
+ <$builder>::for_offer_using_keys(
+ &$self.inner, payment_paths, created_at, payment_hash, keys
)
}
+} }
+
+impl VerifiedInvoiceRequest {
+ offer_accessors!(self, self.inner.contents.inner.offer);
+ invoice_request_accessors!(self, self.inner.contents);
+ #[cfg(not(c_bindings))]
+ invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self.inner, InvoiceBuilder<ExplicitSigningPubkey>);
+ #[cfg(c_bindings)]
+ invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self.inner, InvoiceWithExplicitSigningPubkeyBuilder);
+ #[cfg(not(c_bindings))]
+ invoice_request_respond_with_derived_signing_pubkey_methods!(self, self.inner, InvoiceBuilder<DerivedSigningPubkey>);
+ #[cfg(c_bindings)]
+ invoice_request_respond_with_derived_signing_pubkey_methods!(self, self.inner, InvoiceWithDerivedSigningPubkeyBuilder);
}
impl InvoiceRequestContents {
use bitcoin::blockdata::constants::ChainHash;
use bitcoin::network::constants::Network;
use bitcoin::secp256k1::{KeyPair, Secp256k1, SecretKey, self};
- use core::convert::{Infallible, TryFrom};
use core::num::NonZeroU64;
#[cfg(feature = "std")]
use core::time::Duration;
.build().unwrap()
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap();
+ #[cfg(c_bindings)]
+ let mut unsigned_invoice_request = unsigned_invoice_request;
let mut buffer = Vec::new();
unsigned_invoice_request.write(&mut buffer).unwrap();
.build().unwrap()
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
.build().unwrap()
- .sign(|_| Err(()))
+ .sign(fail_sign)
{
Ok(_) => panic!("expected error"),
- Err(e) => assert_eq!(e, SignError::Signing(())),
+ Err(e) => assert_eq!(e, SignError::Signing),
}
match OfferBuilder::new("foo".into(), recipient_pubkey())
.build().unwrap()
.request_invoice(vec![1; 32], keys.public_key()).unwrap()
.build().unwrap()
- .sign::<_, Infallible>(
- |message| Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
+ .sign(|message: &UnsignedInvoiceRequest|
+ Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys))
)
.unwrap();