mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-25 15:20:24 +01:00
Macro-ize InvoiceBuilder
InvoiceBuilder is not exported to bindings because it has methods that take `self` by value and are only implemented for certain type parameterizations. Define these methods using macros such that different builders and related methods can be defined for c_bindings.
This commit is contained in:
parent
3a92c7b08a
commit
07d628e0fa
3 changed files with 130 additions and 111 deletions
|
@ -169,7 +169,7 @@ pub struct DerivedSigningPubkey(KeyPair);
|
||||||
impl SigningPubkeyStrategy for ExplicitSigningPubkey {}
|
impl SigningPubkeyStrategy for ExplicitSigningPubkey {}
|
||||||
impl SigningPubkeyStrategy for DerivedSigningPubkey {}
|
impl SigningPubkeyStrategy for DerivedSigningPubkey {}
|
||||||
|
|
||||||
impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> {
|
macro_rules! invoice_explicit_signing_pubkey_builder_methods { ($self: ident, $self_type: ty) => {
|
||||||
pub(super) fn for_offer(
|
pub(super) fn for_offer(
|
||||||
invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>,
|
invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>,
|
||||||
created_at: Duration, payment_hash: PaymentHash
|
created_at: Duration, payment_hash: PaymentHash
|
||||||
|
@ -203,25 +203,25 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> {
|
||||||
|
|
||||||
/// Builds an unsigned [`Bolt12Invoice`] after checking for valid semantics. It can be signed by
|
/// Builds an unsigned [`Bolt12Invoice`] after checking for valid semantics. It can be signed by
|
||||||
/// [`UnsignedBolt12Invoice::sign`].
|
/// [`UnsignedBolt12Invoice::sign`].
|
||||||
pub fn build(self) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
|
pub fn build($self: $self_type) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
|
||||||
#[cfg(feature = "std")] {
|
#[cfg(feature = "std")] {
|
||||||
if self.invoice.is_offer_or_refund_expired() {
|
if $self.invoice.is_offer_or_refund_expired() {
|
||||||
return Err(Bolt12SemanticError::AlreadyExpired);
|
return Err(Bolt12SemanticError::AlreadyExpired);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))] {
|
#[cfg(not(feature = "std"))] {
|
||||||
if self.invoice.is_offer_or_refund_expired_no_std(self.invoice.created_at()) {
|
if $self.invoice.is_offer_or_refund_expired_no_std($self.invoice.created_at()) {
|
||||||
return Err(Bolt12SemanticError::AlreadyExpired);
|
return Err(Bolt12SemanticError::AlreadyExpired);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let InvoiceBuilder { invreq_bytes, invoice, .. } = self;
|
let InvoiceBuilder { invreq_bytes, invoice, .. } = $self;
|
||||||
Ok(UnsignedBolt12Invoice::new(invreq_bytes, invoice))
|
Ok(UnsignedBolt12Invoice::new(invreq_bytes, invoice))
|
||||||
}
|
}
|
||||||
}
|
} }
|
||||||
|
|
||||||
impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
|
macro_rules! invoice_derived_signing_pubkey_builder_methods { ($self: ident, $self_type: ty) => {
|
||||||
pub(super) fn for_offer_using_keys(
|
pub(super) fn for_offer_using_keys(
|
||||||
invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>,
|
invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>,
|
||||||
created_at: Duration, payment_hash: PaymentHash, keys: KeyPair
|
created_at: Duration, payment_hash: PaymentHash, keys: KeyPair
|
||||||
|
@ -256,23 +256,23 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
|
||||||
|
|
||||||
/// Builds a signed [`Bolt12Invoice`] after checking for valid semantics.
|
/// Builds a signed [`Bolt12Invoice`] after checking for valid semantics.
|
||||||
pub fn build_and_sign<T: secp256k1::Signing>(
|
pub fn build_and_sign<T: secp256k1::Signing>(
|
||||||
self, secp_ctx: &Secp256k1<T>
|
$self: $self_type, secp_ctx: &Secp256k1<T>
|
||||||
) -> Result<Bolt12Invoice, Bolt12SemanticError> {
|
) -> Result<Bolt12Invoice, Bolt12SemanticError> {
|
||||||
#[cfg(feature = "std")] {
|
#[cfg(feature = "std")] {
|
||||||
if self.invoice.is_offer_or_refund_expired() {
|
if $self.invoice.is_offer_or_refund_expired() {
|
||||||
return Err(Bolt12SemanticError::AlreadyExpired);
|
return Err(Bolt12SemanticError::AlreadyExpired);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))] {
|
#[cfg(not(feature = "std"))] {
|
||||||
if self.invoice.is_offer_or_refund_expired_no_std(self.invoice.created_at()) {
|
if $self.invoice.is_offer_or_refund_expired_no_std($self.invoice.created_at()) {
|
||||||
return Err(Bolt12SemanticError::AlreadyExpired);
|
return Err(Bolt12SemanticError::AlreadyExpired);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let InvoiceBuilder {
|
let InvoiceBuilder {
|
||||||
invreq_bytes, invoice, signing_pubkey_strategy: DerivedSigningPubkey(keys)
|
invreq_bytes, invoice, signing_pubkey_strategy: DerivedSigningPubkey(keys)
|
||||||
} = self;
|
} = $self;
|
||||||
let unsigned_invoice = UnsignedBolt12Invoice::new(invreq_bytes, invoice);
|
let unsigned_invoice = UnsignedBolt12Invoice::new(invreq_bytes, invoice);
|
||||||
|
|
||||||
let invoice = unsigned_invoice
|
let invoice = unsigned_invoice
|
||||||
|
@ -282,9 +282,11 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Ok(invoice)
|
Ok(invoice)
|
||||||
}
|
}
|
||||||
}
|
} }
|
||||||
|
|
||||||
impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> {
|
macro_rules! invoice_builder_methods { (
|
||||||
|
$self: ident, $self_type: ty, $return_type: ty, $return_value: expr
|
||||||
|
) => {
|
||||||
pub(crate) fn amount_msats(
|
pub(crate) fn amount_msats(
|
||||||
invoice_request: &InvoiceRequest
|
invoice_request: &InvoiceRequest
|
||||||
) -> Result<u64, Bolt12SemanticError> {
|
) -> Result<u64, Bolt12SemanticError> {
|
||||||
|
@ -326,57 +328,69 @@ impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> {
|
||||||
/// [`Bolt12Invoice::is_expired`].
|
/// [`Bolt12Invoice::is_expired`].
|
||||||
///
|
///
|
||||||
/// Successive calls to this method will override the previous setting.
|
/// Successive calls to this method will override the previous setting.
|
||||||
pub fn relative_expiry(mut self, relative_expiry_secs: u32) -> Self {
|
pub fn relative_expiry(mut $self: $self_type, relative_expiry_secs: u32) -> $return_type {
|
||||||
let relative_expiry = Duration::from_secs(relative_expiry_secs as u64);
|
let relative_expiry = Duration::from_secs(relative_expiry_secs as u64);
|
||||||
self.invoice.fields_mut().relative_expiry = Some(relative_expiry);
|
$self.invoice.fields_mut().relative_expiry = Some(relative_expiry);
|
||||||
self
|
$return_value
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a P2WSH address to [`Bolt12Invoice::fallbacks`].
|
/// Adds a P2WSH address to [`Bolt12Invoice::fallbacks`].
|
||||||
///
|
///
|
||||||
/// Successive calls to this method will add another address. Caller is responsible for not
|
/// Successive calls to this method will add another address. Caller is responsible for not
|
||||||
/// adding duplicate addresses and only calling if capable of receiving to P2WSH addresses.
|
/// adding duplicate addresses and only calling if capable of receiving to P2WSH addresses.
|
||||||
pub fn fallback_v0_p2wsh(mut self, script_hash: &WScriptHash) -> Self {
|
pub fn fallback_v0_p2wsh(mut $self: $self_type, script_hash: &WScriptHash) -> $return_type {
|
||||||
let address = FallbackAddress {
|
let address = FallbackAddress {
|
||||||
version: WitnessVersion::V0.to_num(),
|
version: WitnessVersion::V0.to_num(),
|
||||||
program: Vec::from(script_hash.to_byte_array()),
|
program: Vec::from(script_hash.to_byte_array()),
|
||||||
};
|
};
|
||||||
self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
|
$self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
|
||||||
self
|
$return_value
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a P2WPKH address to [`Bolt12Invoice::fallbacks`].
|
/// Adds a P2WPKH address to [`Bolt12Invoice::fallbacks`].
|
||||||
///
|
///
|
||||||
/// Successive calls to this method will add another address. Caller is responsible for not
|
/// Successive calls to this method will add another address. Caller is responsible for not
|
||||||
/// adding duplicate addresses and only calling if capable of receiving to P2WPKH addresses.
|
/// adding duplicate addresses and only calling if capable of receiving to P2WPKH addresses.
|
||||||
pub fn fallback_v0_p2wpkh(mut self, pubkey_hash: &WPubkeyHash) -> Self {
|
pub fn fallback_v0_p2wpkh(mut $self: $self_type, pubkey_hash: &WPubkeyHash) -> $return_type {
|
||||||
let address = FallbackAddress {
|
let address = FallbackAddress {
|
||||||
version: WitnessVersion::V0.to_num(),
|
version: WitnessVersion::V0.to_num(),
|
||||||
program: Vec::from(pubkey_hash.to_byte_array()),
|
program: Vec::from(pubkey_hash.to_byte_array()),
|
||||||
};
|
};
|
||||||
self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
|
$self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
|
||||||
self
|
$return_value
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a P2TR address to [`Bolt12Invoice::fallbacks`].
|
/// Adds a P2TR address to [`Bolt12Invoice::fallbacks`].
|
||||||
///
|
///
|
||||||
/// Successive calls to this method will add another address. Caller is responsible for not
|
/// Successive calls to this method will add another address. Caller is responsible for not
|
||||||
/// adding duplicate addresses and only calling if capable of receiving to P2TR addresses.
|
/// adding duplicate addresses and only calling if capable of receiving to P2TR addresses.
|
||||||
pub fn fallback_v1_p2tr_tweaked(mut self, output_key: &TweakedPublicKey) -> Self {
|
pub fn fallback_v1_p2tr_tweaked(mut $self: $self_type, output_key: &TweakedPublicKey) -> $return_type {
|
||||||
let address = FallbackAddress {
|
let address = FallbackAddress {
|
||||||
version: WitnessVersion::V1.to_num(),
|
version: WitnessVersion::V1.to_num(),
|
||||||
program: Vec::from(&output_key.serialize()[..]),
|
program: Vec::from(&output_key.serialize()[..]),
|
||||||
};
|
};
|
||||||
self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
|
$self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
|
||||||
self
|
$return_value
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets [`Bolt12Invoice::invoice_features`] to indicate MPP may be used. Otherwise, MPP is
|
/// Sets [`Bolt12Invoice::invoice_features`] to indicate MPP may be used. Otherwise, MPP is
|
||||||
/// disallowed.
|
/// disallowed.
|
||||||
pub fn allow_mpp(mut self) -> Self {
|
pub fn allow_mpp(mut $self: $self_type) -> $return_type {
|
||||||
self.invoice.fields_mut().features.set_basic_mpp_optional();
|
$self.invoice.fields_mut().features.set_basic_mpp_optional();
|
||||||
self
|
$return_value
|
||||||
}
|
}
|
||||||
|
} }
|
||||||
|
|
||||||
|
impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> {
|
||||||
|
invoice_explicit_signing_pubkey_builder_methods!(self, Self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
|
||||||
|
invoice_derived_signing_pubkey_builder_methods!(self, Self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> {
|
||||||
|
invoice_builder_methods!(self, Self, Self, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A semantically valid [`Bolt12Invoice`] that hasn't been signed.
|
/// A semantically valid [`Bolt12Invoice`] that hasn't been signed.
|
||||||
|
@ -412,32 +426,38 @@ impl UnsignedBolt12Invoice {
|
||||||
pub fn tagged_hash(&self) -> &TaggedHash {
|
pub fn tagged_hash(&self) -> &TaggedHash {
|
||||||
&self.tagged_hash
|
&self.tagged_hash
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! unsigned_invoice_sign_method { ($self: ident, $self_type: ty) => {
|
||||||
/// Signs the [`TaggedHash`] of the invoice using the given function.
|
/// Signs the [`TaggedHash`] of the invoice using the given function.
|
||||||
///
|
///
|
||||||
/// Note: The hash computation may have included unknown, odd TLV records.
|
/// Note: The hash computation may have included unknown, odd TLV records.
|
||||||
///
|
///
|
||||||
/// This is not exported to bindings users as functions aren't currently mapped.
|
/// This is not exported to bindings users as functions aren't currently mapped.
|
||||||
pub fn sign<F, E>(mut self, sign: F) -> Result<Bolt12Invoice, SignError<E>>
|
pub fn sign<F, E>(mut $self: $self_type, sign: F) -> Result<Bolt12Invoice, SignError<E>>
|
||||||
where
|
where
|
||||||
F: FnOnce(&Self) -> Result<Signature, E>
|
F: FnOnce(&Self) -> Result<Signature, E>
|
||||||
{
|
{
|
||||||
let pubkey = self.contents.fields().signing_pubkey;
|
let pubkey = $self.contents.fields().signing_pubkey;
|
||||||
let signature = merkle::sign_message(sign, &self, pubkey)?;
|
let signature = merkle::sign_message(sign, &$self, pubkey)?;
|
||||||
|
|
||||||
// Append the signature TLV record to the bytes.
|
// Append the signature TLV record to the bytes.
|
||||||
let signature_tlv_stream = SignatureTlvStreamRef {
|
let signature_tlv_stream = SignatureTlvStreamRef {
|
||||||
signature: Some(&signature),
|
signature: Some(&signature),
|
||||||
};
|
};
|
||||||
signature_tlv_stream.write(&mut self.bytes).unwrap();
|
signature_tlv_stream.write(&mut $self.bytes).unwrap();
|
||||||
|
|
||||||
Ok(Bolt12Invoice {
|
Ok(Bolt12Invoice {
|
||||||
bytes: self.bytes,
|
bytes: $self.bytes,
|
||||||
contents: self.contents,
|
contents: $self.contents,
|
||||||
signature,
|
signature,
|
||||||
tagged_hash: self.tagged_hash,
|
tagged_hash: $self.tagged_hash,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
} }
|
||||||
|
|
||||||
|
impl UnsignedBolt12Invoice {
|
||||||
|
unsigned_invoice_sign_method!(self, Self);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRef<TaggedHash> for UnsignedBolt12Invoice {
|
impl AsRef<TaggedHash> for UnsignedBolt12Invoice {
|
||||||
|
|
|
@ -662,17 +662,9 @@ impl UnsignedInvoiceRequest {
|
||||||
invoice_request_accessors!(self, self.contents);
|
invoice_request_accessors!(self, self.contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InvoiceRequest {
|
macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { (
|
||||||
offer_accessors!(self, self.contents.inner.offer);
|
$self: ident, $contents: expr, $builder: ty
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an [`InvoiceBuilder`] for the request with the given required fields and using the
|
/// 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.
|
/// [`Duration`] since [`std::time::SystemTime::UNIX_EPOCH`] as the creation time.
|
||||||
///
|
///
|
||||||
|
@ -684,13 +676,13 @@ impl InvoiceRequest {
|
||||||
/// [`Duration`]: core::time::Duration
|
/// [`Duration`]: core::time::Duration
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn respond_with(
|
pub fn respond_with(
|
||||||
&self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash
|
&$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash
|
||||||
) -> Result<InvoiceBuilder<ExplicitSigningPubkey>, Bolt12SemanticError> {
|
) -> Result<$builder, Bolt12SemanticError> {
|
||||||
let created_at = std::time::SystemTime::now()
|
let created_at = std::time::SystemTime::now()
|
||||||
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
||||||
.expect("SystemTime::now() should come after 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.
|
/// Creates an [`InvoiceBuilder`] for the request with the given required fields.
|
||||||
|
@ -719,31 +711,48 @@ impl InvoiceRequest {
|
||||||
/// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
|
/// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
|
||||||
/// [`OfferBuilder::deriving_signing_pubkey`]: crate::offers::offer::OfferBuilder::deriving_signing_pubkey
|
/// [`OfferBuilder::deriving_signing_pubkey`]: crate::offers::offer::OfferBuilder::deriving_signing_pubkey
|
||||||
pub fn respond_with_no_std(
|
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
|
created_at: core::time::Duration
|
||||||
) -> Result<InvoiceBuilder<ExplicitSigningPubkey>, Bolt12SemanticError> {
|
) -> Result<$builder, Bolt12SemanticError> {
|
||||||
if self.invoice_request_features().requires_unknown_bits() {
|
if $contents.invoice_request_features().requires_unknown_bits() {
|
||||||
return Err(Bolt12SemanticError::UnknownRequiredFeatures);
|
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
|
/// 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
|
/// request which contains the derived keys needed to sign a [`Bolt12Invoice`] for the request
|
||||||
/// if they could be extracted from the metadata.
|
/// if they could be extracted from the metadata.
|
||||||
///
|
///
|
||||||
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
||||||
pub fn verify<T: secp256k1::Signing>(
|
pub fn verify<T: secp256k1::Signing>(
|
||||||
self, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
|
$self: $self_type, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
|
||||||
) -> Result<VerifiedInvoiceRequest, ()> {
|
) -> 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 {
|
Ok(VerifiedInvoiceRequest {
|
||||||
inner: self,
|
inner: $self,
|
||||||
keys,
|
keys,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/// 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 {
|
pub(crate) fn as_tlv_stream(&self) -> FullInvoiceRequestTlvStreamRef {
|
||||||
let (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) =
|
let (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) =
|
||||||
self.contents.as_tlv_stream();
|
self.contents.as_tlv_stream();
|
||||||
|
@ -754,37 +763,9 @@ impl InvoiceRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VerifiedInvoiceRequest {
|
macro_rules! invoice_request_respond_with_derived_signing_pubkey_methods { (
|
||||||
offer_accessors!(self, self.inner.contents.inner.offer);
|
$self: ident, $contents: expr, $builder: ty
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
|
/// 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
|
/// derived signing keys from the originating [`Offer`] to sign the [`Bolt12Invoice`]. Must use
|
||||||
/// the same [`ExpandedKey`] as the one used to create the offer.
|
/// the same [`ExpandedKey`] as the one used to create the offer.
|
||||||
|
@ -796,13 +777,13 @@ impl VerifiedInvoiceRequest {
|
||||||
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn respond_using_derived_keys(
|
pub fn respond_using_derived_keys(
|
||||||
&self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash
|
&$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash
|
||||||
) -> Result<InvoiceBuilder<DerivedSigningPubkey>, Bolt12SemanticError> {
|
) -> Result<$builder, Bolt12SemanticError> {
|
||||||
let created_at = std::time::SystemTime::now()
|
let created_at = std::time::SystemTime::now()
|
||||||
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
||||||
.expect("SystemTime::now() should come after 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
|
/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
|
||||||
|
@ -815,22 +796,29 @@ impl VerifiedInvoiceRequest {
|
||||||
///
|
///
|
||||||
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
||||||
pub fn respond_using_derived_keys_no_std(
|
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
|
created_at: core::time::Duration
|
||||||
) -> Result<InvoiceBuilder<DerivedSigningPubkey>, Bolt12SemanticError> {
|
) -> Result<$builder, Bolt12SemanticError> {
|
||||||
if self.inner.invoice_request_features().requires_unknown_bits() {
|
if $self.inner.invoice_request_features().requires_unknown_bits() {
|
||||||
return Err(Bolt12SemanticError::UnknownRequiredFeatures);
|
return Err(Bolt12SemanticError::UnknownRequiredFeatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
let keys = match self.keys {
|
let keys = match $self.keys {
|
||||||
None => return Err(Bolt12SemanticError::InvalidMetadata),
|
None => return Err(Bolt12SemanticError::InvalidMetadata),
|
||||||
Some(keys) => keys,
|
Some(keys) => keys,
|
||||||
};
|
};
|
||||||
|
|
||||||
InvoiceBuilder::for_offer_using_keys(
|
<$builder>::for_offer_using_keys(
|
||||||
&self.inner, payment_paths, created_at, payment_hash, 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);
|
||||||
|
invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self.inner, InvoiceBuilder<ExplicitSigningPubkey>);
|
||||||
|
invoice_request_respond_with_derived_signing_pubkey_methods!(self, self.inner, InvoiceBuilder<DerivedSigningPubkey>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InvoiceRequestContents {
|
impl InvoiceRequestContents {
|
||||||
|
|
|
@ -480,7 +480,9 @@ impl Refund {
|
||||||
pub fn payer_note(&self) -> Option<PrintableString> {
|
pub fn payer_note(&self) -> Option<PrintableString> {
|
||||||
self.contents.payer_note()
|
self.contents.payer_note()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! respond_with_explicit_signing_pubkey_methods { ($self: ident, $builder: ty) => {
|
||||||
/// Creates an [`InvoiceBuilder`] for the refund with the given required fields and using the
|
/// Creates an [`InvoiceBuilder`] for the refund with the given required fields and using the
|
||||||
/// [`Duration`] since [`std::time::SystemTime::UNIX_EPOCH`] as the creation time.
|
/// [`Duration`] since [`std::time::SystemTime::UNIX_EPOCH`] as the creation time.
|
||||||
///
|
///
|
||||||
|
@ -492,14 +494,14 @@ impl Refund {
|
||||||
/// [`Duration`]: core::time::Duration
|
/// [`Duration`]: core::time::Duration
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn respond_with(
|
pub fn respond_with(
|
||||||
&self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
|
&$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
|
||||||
signing_pubkey: PublicKey,
|
signing_pubkey: PublicKey,
|
||||||
) -> Result<InvoiceBuilder<ExplicitSigningPubkey>, Bolt12SemanticError> {
|
) -> Result<$builder, Bolt12SemanticError> {
|
||||||
let created_at = std::time::SystemTime::now()
|
let created_at = std::time::SystemTime::now()
|
||||||
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
||||||
.expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
|
.expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
|
||||||
|
|
||||||
self.respond_with_no_std(payment_paths, payment_hash, signing_pubkey, created_at)
|
$self.respond_with_no_std(payment_paths, payment_hash, signing_pubkey, created_at)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an [`InvoiceBuilder`] for the refund with the given required fields.
|
/// Creates an [`InvoiceBuilder`] for the refund with the given required fields.
|
||||||
|
@ -525,16 +527,18 @@ impl Refund {
|
||||||
///
|
///
|
||||||
/// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
|
/// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
|
||||||
pub fn respond_with_no_std(
|
pub fn respond_with_no_std(
|
||||||
&self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
|
&$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
|
||||||
signing_pubkey: PublicKey, created_at: Duration
|
signing_pubkey: PublicKey, created_at: Duration
|
||||||
) -> Result<InvoiceBuilder<ExplicitSigningPubkey>, Bolt12SemanticError> {
|
) -> Result<$builder, Bolt12SemanticError> {
|
||||||
if self.features().requires_unknown_bits() {
|
if $self.features().requires_unknown_bits() {
|
||||||
return Err(Bolt12SemanticError::UnknownRequiredFeatures);
|
return Err(Bolt12SemanticError::UnknownRequiredFeatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
InvoiceBuilder::for_refund(self, payment_paths, created_at, payment_hash, signing_pubkey)
|
<$builder>::for_refund($self, payment_paths, created_at, payment_hash, signing_pubkey)
|
||||||
}
|
}
|
||||||
|
} }
|
||||||
|
|
||||||
|
macro_rules! respond_with_derived_signing_pubkey_methods { ($self: ident, $builder: ty) => {
|
||||||
/// Creates an [`InvoiceBuilder`] for the refund using the given required fields and that uses
|
/// Creates an [`InvoiceBuilder`] for the refund using the given required fields and that uses
|
||||||
/// derived signing keys to sign the [`Bolt12Invoice`].
|
/// derived signing keys to sign the [`Bolt12Invoice`].
|
||||||
///
|
///
|
||||||
|
@ -545,9 +549,9 @@ impl Refund {
|
||||||
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn respond_using_derived_keys<ES: Deref>(
|
pub fn respond_using_derived_keys<ES: Deref>(
|
||||||
&self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
|
&$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
|
||||||
expanded_key: &ExpandedKey, entropy_source: ES
|
expanded_key: &ExpandedKey, entropy_source: ES
|
||||||
) -> Result<InvoiceBuilder<DerivedSigningPubkey>, Bolt12SemanticError>
|
) -> Result<$builder, Bolt12SemanticError>
|
||||||
where
|
where
|
||||||
ES::Target: EntropySource,
|
ES::Target: EntropySource,
|
||||||
{
|
{
|
||||||
|
@ -555,7 +559,7 @@ impl Refund {
|
||||||
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
||||||
.expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
|
.expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
|
||||||
|
|
||||||
self.respond_using_derived_keys_no_std(
|
$self.respond_using_derived_keys_no_std(
|
||||||
payment_paths, payment_hash, created_at, expanded_key, entropy_source
|
payment_paths, payment_hash, created_at, expanded_key, entropy_source
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -569,22 +573,29 @@ impl Refund {
|
||||||
///
|
///
|
||||||
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
||||||
pub fn respond_using_derived_keys_no_std<ES: Deref>(
|
pub fn respond_using_derived_keys_no_std<ES: Deref>(
|
||||||
&self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
|
&$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash,
|
||||||
created_at: core::time::Duration, expanded_key: &ExpandedKey, entropy_source: ES
|
created_at: core::time::Duration, expanded_key: &ExpandedKey, entropy_source: ES
|
||||||
) -> Result<InvoiceBuilder<DerivedSigningPubkey>, Bolt12SemanticError>
|
) -> Result<$builder, Bolt12SemanticError>
|
||||||
where
|
where
|
||||||
ES::Target: EntropySource,
|
ES::Target: EntropySource,
|
||||||
{
|
{
|
||||||
if self.features().requires_unknown_bits() {
|
if $self.features().requires_unknown_bits() {
|
||||||
return Err(Bolt12SemanticError::UnknownRequiredFeatures);
|
return Err(Bolt12SemanticError::UnknownRequiredFeatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
let nonce = Nonce::from_entropy_source(entropy_source);
|
let nonce = Nonce::from_entropy_source(entropy_source);
|
||||||
let keys = signer::derive_keys(nonce, expanded_key);
|
let keys = signer::derive_keys(nonce, expanded_key);
|
||||||
InvoiceBuilder::for_refund_using_keys(self, payment_paths, created_at, payment_hash, keys)
|
<$builder>::for_refund_using_keys($self, payment_paths, created_at, payment_hash, keys)
|
||||||
}
|
}
|
||||||
|
} }
|
||||||
|
|
||||||
#[cfg(test)]
|
impl Refund {
|
||||||
|
respond_with_explicit_signing_pubkey_methods!(self, InvoiceBuilder<ExplicitSigningPubkey>);
|
||||||
|
respond_with_derived_signing_pubkey_methods!(self, InvoiceBuilder<DerivedSigningPubkey>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
impl Refund {
|
||||||
fn as_tlv_stream(&self) -> RefundTlvStreamRef {
|
fn as_tlv_stream(&self) -> RefundTlvStreamRef {
|
||||||
self.contents.as_tlv_stream()
|
self.contents.as_tlv_stream()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue