mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-25 07:17:40 +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 DerivedSigningPubkey {}
|
||||
|
||||
impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> {
|
||||
macro_rules! invoice_explicit_signing_pubkey_builder_methods { ($self: ident, $self_type: ty) => {
|
||||
pub(super) fn for_offer(
|
||||
invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>,
|
||||
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
|
||||
/// [`UnsignedBolt12Invoice::sign`].
|
||||
pub fn build(self) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
|
||||
pub fn build($self: $self_type) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
|
||||
#[cfg(feature = "std")] {
|
||||
if self.invoice.is_offer_or_refund_expired() {
|
||||
if $self.invoice.is_offer_or_refund_expired() {
|
||||
return Err(Bolt12SemanticError::AlreadyExpired);
|
||||
}
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
}
|
||||
|
||||
let InvoiceBuilder { invreq_bytes, invoice, .. } = self;
|
||||
let InvoiceBuilder { invreq_bytes, invoice, .. } = $self;
|
||||
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(
|
||||
invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>,
|
||||
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.
|
||||
pub fn build_and_sign<T: secp256k1::Signing>(
|
||||
self, secp_ctx: &Secp256k1<T>
|
||||
$self: $self_type, secp_ctx: &Secp256k1<T>
|
||||
) -> Result<Bolt12Invoice, Bolt12SemanticError> {
|
||||
#[cfg(feature = "std")] {
|
||||
if self.invoice.is_offer_or_refund_expired() {
|
||||
if $self.invoice.is_offer_or_refund_expired() {
|
||||
return Err(Bolt12SemanticError::AlreadyExpired);
|
||||
}
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
}
|
||||
|
||||
let InvoiceBuilder {
|
||||
invreq_bytes, invoice, signing_pubkey_strategy: DerivedSigningPubkey(keys)
|
||||
} = self;
|
||||
} = $self;
|
||||
let unsigned_invoice = UnsignedBolt12Invoice::new(invreq_bytes, invoice);
|
||||
|
||||
let invoice = unsigned_invoice
|
||||
|
@ -282,9 +282,11 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> {
|
|||
.unwrap();
|
||||
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(
|
||||
invoice_request: &InvoiceRequest
|
||||
) -> Result<u64, Bolt12SemanticError> {
|
||||
|
@ -326,57 +328,69 @@ impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> {
|
|||
/// [`Bolt12Invoice::is_expired`].
|
||||
///
|
||||
/// 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);
|
||||
self.invoice.fields_mut().relative_expiry = Some(relative_expiry);
|
||||
self
|
||||
$self.invoice.fields_mut().relative_expiry = Some(relative_expiry);
|
||||
$return_value
|
||||
}
|
||||
|
||||
/// Adds a P2WSH address to [`Bolt12Invoice::fallbacks`].
|
||||
///
|
||||
/// 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.
|
||||
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 {
|
||||
version: WitnessVersion::V0.to_num(),
|
||||
program: Vec::from(script_hash.to_byte_array()),
|
||||
};
|
||||
self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
|
||||
self
|
||||
$self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
|
||||
$return_value
|
||||
}
|
||||
|
||||
/// Adds a P2WPKH address to [`Bolt12Invoice::fallbacks`].
|
||||
///
|
||||
/// 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.
|
||||
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 {
|
||||
version: WitnessVersion::V0.to_num(),
|
||||
program: Vec::from(pubkey_hash.to_byte_array()),
|
||||
};
|
||||
self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
|
||||
self
|
||||
$self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
|
||||
$return_value
|
||||
}
|
||||
|
||||
/// Adds a P2TR address to [`Bolt12Invoice::fallbacks`].
|
||||
///
|
||||
/// 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.
|
||||
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 {
|
||||
version: WitnessVersion::V1.to_num(),
|
||||
program: Vec::from(&output_key.serialize()[..]),
|
||||
};
|
||||
self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
|
||||
self
|
||||
$self.invoice.fields_mut().fallbacks.get_or_insert_with(Vec::new).push(address);
|
||||
$return_value
|
||||
}
|
||||
|
||||
/// Sets [`Bolt12Invoice::invoice_features`] to indicate MPP may be used. Otherwise, MPP is
|
||||
/// disallowed.
|
||||
pub fn allow_mpp(mut self) -> Self {
|
||||
self.invoice.fields_mut().features.set_basic_mpp_optional();
|
||||
self
|
||||
pub fn allow_mpp(mut $self: $self_type) -> $return_type {
|
||||
$self.invoice.fields_mut().features.set_basic_mpp_optional();
|
||||
$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.
|
||||
|
@ -412,32 +426,38 @@ impl UnsignedBolt12Invoice {
|
|||
pub fn tagged_hash(&self) -> &TaggedHash {
|
||||
&self.tagged_hash
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! unsigned_invoice_sign_method { ($self: ident, $self_type: ty) => {
|
||||
/// Signs the [`TaggedHash`] of the invoice using the given function.
|
||||
///
|
||||
/// Note: The hash computation may have included unknown, odd TLV records.
|
||||
///
|
||||
/// 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
|
||||
F: FnOnce(&Self) -> Result<Signature, E>
|
||||
{
|
||||
let pubkey = self.contents.fields().signing_pubkey;
|
||||
let signature = merkle::sign_message(sign, &self, pubkey)?;
|
||||
let pubkey = $self.contents.fields().signing_pubkey;
|
||||
let signature = merkle::sign_message(sign, &$self, pubkey)?;
|
||||
|
||||
// Append the signature TLV record to the bytes.
|
||||
let signature_tlv_stream = SignatureTlvStreamRef {
|
||||
signature: Some(&signature),
|
||||
};
|
||||
signature_tlv_stream.write(&mut self.bytes).unwrap();
|
||||
signature_tlv_stream.write(&mut $self.bytes).unwrap();
|
||||
|
||||
Ok(Bolt12Invoice {
|
||||
bytes: self.bytes,
|
||||
contents: self.contents,
|
||||
bytes: $self.bytes,
|
||||
contents: $self.contents,
|
||||
signature,
|
||||
tagged_hash: self.tagged_hash,
|
||||
tagged_hash: $self.tagged_hash,
|
||||
})
|
||||
}
|
||||
} }
|
||||
|
||||
impl UnsignedBolt12Invoice {
|
||||
unsigned_invoice_sign_method!(self, Self);
|
||||
}
|
||||
|
||||
impl AsRef<TaggedHash> for UnsignedBolt12Invoice {
|
||||
|
|
|
@ -662,17 +662,9 @@ impl 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.
|
||||
///
|
||||
|
@ -684,13 +676,13 @@ impl InvoiceRequest {
|
|||
/// [`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.
|
||||
|
@ -719,31 +711,48 @@ impl InvoiceRequest {
|
|||
/// [`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>
|
||||
$self: $self_type, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
|
||||
) -> 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,
|
||||
inner: $self,
|
||||
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 {
|
||||
let (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) =
|
||||
self.contents.as_tlv_stream();
|
||||
|
@ -754,37 +763,9 @@ impl InvoiceRequest {
|
|||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -796,13 +777,13 @@ impl VerifiedInvoiceRequest {
|
|||
/// [`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
|
||||
|
@ -815,22 +796,29 @@ impl VerifiedInvoiceRequest {
|
|||
///
|
||||
/// [`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);
|
||||
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 {
|
||||
|
|
|
@ -480,7 +480,9 @@ impl Refund {
|
|||
pub fn payer_note(&self) -> Option<PrintableString> {
|
||||
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
|
||||
/// [`Duration`] since [`std::time::SystemTime::UNIX_EPOCH`] as the creation time.
|
||||
///
|
||||
|
@ -492,14 +494,14 @@ impl Refund {
|
|||
/// [`Duration`]: core::time::Duration
|
||||
#[cfg(feature = "std")]
|
||||
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,
|
||||
) -> Result<InvoiceBuilder<ExplicitSigningPubkey>, Bolt12SemanticError> {
|
||||
) -> 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, 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.
|
||||
|
@ -525,16 +527,18 @@ impl Refund {
|
|||
///
|
||||
/// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
|
||||
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
|
||||
) -> Result<InvoiceBuilder<ExplicitSigningPubkey>, Bolt12SemanticError> {
|
||||
if self.features().requires_unknown_bits() {
|
||||
) -> Result<$builder, Bolt12SemanticError> {
|
||||
if $self.features().requires_unknown_bits() {
|
||||
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
|
||||
/// derived signing keys to sign the [`Bolt12Invoice`].
|
||||
///
|
||||
|
@ -545,9 +549,9 @@ impl Refund {
|
|||
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
||||
#[cfg(feature = "std")]
|
||||
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
|
||||
) -> Result<InvoiceBuilder<DerivedSigningPubkey>, Bolt12SemanticError>
|
||||
) -> Result<$builder, Bolt12SemanticError>
|
||||
where
|
||||
ES::Target: EntropySource,
|
||||
{
|
||||
|
@ -555,7 +559,7 @@ impl Refund {
|
|||
.duration_since(std::time::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
|
||||
)
|
||||
}
|
||||
|
@ -569,22 +573,29 @@ impl Refund {
|
|||
///
|
||||
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
||||
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
|
||||
) -> Result<InvoiceBuilder<DerivedSigningPubkey>, Bolt12SemanticError>
|
||||
) -> Result<$builder, Bolt12SemanticError>
|
||||
where
|
||||
ES::Target: EntropySource,
|
||||
{
|
||||
if self.features().requires_unknown_bits() {
|
||||
if $self.features().requires_unknown_bits() {
|
||||
return Err(Bolt12SemanticError::UnknownRequiredFeatures);
|
||||
}
|
||||
|
||||
let nonce = Nonce::from_entropy_source(entropy_source);
|
||||
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 {
|
||||
self.contents.as_tlv_stream()
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue