From 6aa85bd7fbde825c1bd5b168d8882dbd46bd9d3c Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:54:44 +0100 Subject: [PATCH 01/22] `rustfmt`: Run on `lightning/src/offers/invoice.rs` --- lightning/src/offers/invoice.rs | 1720 ++++++++++++++++++++----------- 1 file changed, 1090 insertions(+), 630 deletions(-) diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index 9d2401e2ca0..be3886346c5 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -1,4 +1,4 @@ - // This file is Copyright its original authors, visible in version control +// This file is Copyright its original authors, visible in version control // history. // // This file is licensed under the Apache License, Version 2.0 >::from( //! InvoiceRequest::try_from(bytes)? -#![cfg_attr(feature = "std", doc = " +#![cfg_attr( + feature = "std", + doc = " .respond_with(payment_paths, payment_hash)? -")] -#![cfg_attr(not(feature = "std"), doc = " +" +)] +#![cfg_attr( + not(feature = "std"), + doc = " .respond_with_no_std(payment_paths, payment_hash, core::time::Duration::from_secs(0))? -")] +" +)] //! # ) //! .relative_expiry(3600) //! .allow_mpp() @@ -80,12 +86,18 @@ //! # >::from( //! "lnr1qcp4256ypq" //! .parse::()? -#![cfg_attr(feature = "std", doc = " +#![cfg_attr( + feature = "std", + doc = " .respond_with(payment_paths, payment_hash, pubkey)? -")] -#![cfg_attr(not(feature = "std"), doc = " +" +)] +#![cfg_attr( + not(feature = "std"), + doc = " .respond_with_no_std(payment_paths, payment_hash, pubkey, core::time::Duration::from_secs(0))? -")] +" +)] //! # ) //! .relative_expiry(3600) //! .allow_mpp() @@ -102,35 +114,51 @@ //! //! ``` -use bitcoin::{WitnessProgram, Network, WitnessVersion}; -use bitcoin::constants::ChainHash; -use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, self}; -use bitcoin::secp256k1::schnorr::Signature; -use bitcoin::address::Address; -use core::time::Duration; -use core::hash::{Hash, Hasher}; -use crate::io; -use crate::blinded_path::BlindedPath; use crate::blinded_path::message::BlindedMessagePath; use crate::blinded_path::payment::{BlindedPayInfo, BlindedPaymentPath}; -use crate::types::payment::PaymentHash; +use crate::blinded_path::BlindedPath; +use crate::io; use crate::ln::channelmanager::PaymentId; -use crate::types::features::{Bolt12InvoiceFeatures, InvoiceRequestFeatures, OfferFeatures}; use crate::ln::inbound_payment::{ExpandedKey, IV_LEN}; use crate::ln::msgs::DecodeError; -use crate::offers::invoice_macros::{invoice_accessors_common, invoice_builder_methods_common}; #[cfg(test)] use crate::offers::invoice_macros::invoice_builder_methods_test_common; -use crate::offers::invoice_request::{EXPERIMENTAL_INVOICE_REQUEST_TYPES, ExperimentalInvoiceRequestTlvStream, ExperimentalInvoiceRequestTlvStreamRef, INVOICE_REQUEST_PAYER_ID_TYPE, INVOICE_REQUEST_TYPES, IV_BYTES as INVOICE_REQUEST_IV_BYTES, InvoiceRequest, InvoiceRequestContents, InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef}; -use crate::offers::merkle::{SignError, SignFn, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, TlvStream, self}; +use crate::offers::invoice_macros::{invoice_accessors_common, invoice_builder_methods_common}; +use crate::offers::invoice_request::{ + ExperimentalInvoiceRequestTlvStream, ExperimentalInvoiceRequestTlvStreamRef, InvoiceRequest, + InvoiceRequestContents, InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef, + EXPERIMENTAL_INVOICE_REQUEST_TYPES, INVOICE_REQUEST_PAYER_ID_TYPE, INVOICE_REQUEST_TYPES, + IV_BYTES as INVOICE_REQUEST_IV_BYTES, +}; +use crate::offers::merkle::{ + self, SignError, SignFn, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, TlvStream, +}; use crate::offers::nonce::Nonce; -use crate::offers::offer::{Amount, EXPERIMENTAL_OFFER_TYPES, ExperimentalOfferTlvStream, ExperimentalOfferTlvStreamRef, OFFER_TYPES, OfferTlvStream, OfferTlvStreamRef, Quantity}; +use crate::offers::offer::{ + Amount, ExperimentalOfferTlvStream, ExperimentalOfferTlvStreamRef, OfferTlvStream, + OfferTlvStreamRef, Quantity, EXPERIMENTAL_OFFER_TYPES, OFFER_TYPES, +}; use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError, ParsedMessage}; -use crate::offers::payer::{PAYER_METADATA_TYPE, PayerTlvStream, PayerTlvStreamRef}; -use crate::offers::refund::{IV_BYTES_WITH_METADATA as REFUND_IV_BYTES_WITH_METADATA, IV_BYTES_WITHOUT_METADATA as REFUND_IV_BYTES_WITHOUT_METADATA, Refund, RefundContents}; -use crate::offers::signer::{Metadata, self}; -use crate::util::ser::{CursorReadable, HighZeroBytesDroppedBigSize, Iterable, Readable, WithoutLength, Writeable, Writer}; +use crate::offers::payer::{PayerTlvStream, PayerTlvStreamRef, PAYER_METADATA_TYPE}; +use crate::offers::refund::{ + Refund, RefundContents, IV_BYTES_WITHOUT_METADATA as REFUND_IV_BYTES_WITHOUT_METADATA, + IV_BYTES_WITH_METADATA as REFUND_IV_BYTES_WITH_METADATA, +}; +use crate::offers::signer::{self, Metadata}; +use crate::types::features::{Bolt12InvoiceFeatures, InvoiceRequestFeatures, OfferFeatures}; +use crate::types::payment::PaymentHash; +use crate::util::ser::{ + CursorReadable, HighZeroBytesDroppedBigSize, Iterable, Readable, WithoutLength, Writeable, + Writer, +}; use crate::util::string::PrintableString; +use bitcoin::address::Address; +use bitcoin::constants::ChainHash; +use bitcoin::secp256k1::schnorr::Signature; +use bitcoin::secp256k1::{self, Keypair, PublicKey, Secp256k1}; +use bitcoin::{Network, WitnessProgram, WitnessVersion}; +use core::hash::{Hash, Hasher}; +use core::time::Duration; #[allow(unused_imports)] use crate::prelude::*; @@ -210,175 +238,208 @@ pub struct DerivedSigningPubkey(pub(super) Keypair); impl SigningPubkeyStrategy for ExplicitSigningPubkey {} impl SigningPubkeyStrategy for DerivedSigningPubkey {} -macro_rules! invoice_explicit_signing_pubkey_builder_methods { ($self: ident, $self_type: ty) => { - #[cfg_attr(c_bindings, allow(dead_code))] - pub(super) fn for_offer( - invoice_request: &'a InvoiceRequest, payment_paths: Vec, - created_at: Duration, payment_hash: PaymentHash, signing_pubkey: PublicKey - ) -> Result { - let amount_msats = Self::amount_msats(invoice_request)?; - let contents = InvoiceContents::ForOffer { - invoice_request: invoice_request.contents.clone(), - fields: Self::fields( - payment_paths, created_at, payment_hash, amount_msats, signing_pubkey - ), - }; - - Self::new(&invoice_request.bytes, contents, ExplicitSigningPubkey {}) - } - - #[cfg_attr(c_bindings, allow(dead_code))] - pub(super) fn for_refund( - refund: &'a Refund, payment_paths: Vec, created_at: Duration, - payment_hash: PaymentHash, signing_pubkey: PublicKey - ) -> Result { - let amount_msats = refund.amount_msats(); - let contents = InvoiceContents::ForRefund { - refund: refund.contents.clone(), - fields: Self::fields( - payment_paths, created_at, payment_hash, amount_msats, signing_pubkey - ), - }; - - Self::new(&refund.bytes, contents, ExplicitSigningPubkey {}) - } - - /// Builds an unsigned [`Bolt12Invoice`] after checking for valid semantics. It can be signed by - /// [`UnsignedBolt12Invoice::sign`]. - pub fn build($self: $self_type) -> Result { - #[cfg(feature = "std")] { - if $self.invoice.is_offer_or_refund_expired() { - return Err(Bolt12SemanticError::AlreadyExpired); +macro_rules! invoice_explicit_signing_pubkey_builder_methods { + ($self: ident, $self_type: ty) => { + #[cfg_attr(c_bindings, allow(dead_code))] + pub(super) fn for_offer( + invoice_request: &'a InvoiceRequest, payment_paths: Vec, + created_at: Duration, payment_hash: PaymentHash, signing_pubkey: PublicKey, + ) -> Result { + let amount_msats = Self::amount_msats(invoice_request)?; + let contents = InvoiceContents::ForOffer { + invoice_request: invoice_request.contents.clone(), + fields: Self::fields( + payment_paths, + created_at, + payment_hash, + amount_msats, + signing_pubkey, + ), + }; + + Self::new(&invoice_request.bytes, contents, ExplicitSigningPubkey {}) + } + + #[cfg_attr(c_bindings, allow(dead_code))] + pub(super) fn for_refund( + refund: &'a Refund, payment_paths: Vec, created_at: Duration, + payment_hash: PaymentHash, signing_pubkey: PublicKey, + ) -> Result { + let amount_msats = refund.amount_msats(); + let contents = InvoiceContents::ForRefund { + refund: refund.contents.clone(), + fields: Self::fields( + payment_paths, + created_at, + payment_hash, + amount_msats, + signing_pubkey, + ), + }; + + Self::new(&refund.bytes, contents, ExplicitSigningPubkey {}) + } + + /// Builds an unsigned [`Bolt12Invoice`] after checking for valid semantics. It can be signed by + /// [`UnsignedBolt12Invoice::sign`]. + pub fn build($self: $self_type) -> Result { + #[cfg(feature = "std")] + { + 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()) { - return Err(Bolt12SemanticError::AlreadyExpired); + #[cfg(not(feature = "std"))] + { + if $self.invoice.is_offer_or_refund_expired_no_std($self.invoice.created_at()) { + return Err(Bolt12SemanticError::AlreadyExpired); + } } - } - let Self { invreq_bytes, invoice, .. } = $self; - #[cfg(not(c_bindings))] { - Ok(UnsignedBolt12Invoice::new(invreq_bytes, invoice)) - } - #[cfg(c_bindings)] { - Ok(UnsignedBolt12Invoice::new(invreq_bytes, invoice.clone())) + let Self { invreq_bytes, invoice, .. } = $self; + #[cfg(not(c_bindings))] + { + Ok(UnsignedBolt12Invoice::new(invreq_bytes, invoice)) + } + #[cfg(c_bindings)] + { + Ok(UnsignedBolt12Invoice::new(invreq_bytes, invoice.clone())) + } } - } -} } - -macro_rules! invoice_derived_signing_pubkey_builder_methods { ($self: ident, $self_type: ty) => { - #[cfg_attr(c_bindings, allow(dead_code))] - pub(super) fn for_offer_using_keys( - invoice_request: &'a InvoiceRequest, payment_paths: Vec, - created_at: Duration, payment_hash: PaymentHash, keys: Keypair - ) -> Result { - let amount_msats = Self::amount_msats(invoice_request)?; - let signing_pubkey = keys.public_key(); - let contents = InvoiceContents::ForOffer { - invoice_request: invoice_request.contents.clone(), - fields: Self::fields( - payment_paths, created_at, payment_hash, amount_msats, signing_pubkey - ), - }; - - Self::new(&invoice_request.bytes, contents, DerivedSigningPubkey(keys)) - } - - #[cfg_attr(c_bindings, allow(dead_code))] - pub(super) fn for_refund_using_keys( - refund: &'a Refund, payment_paths: Vec, created_at: Duration, - payment_hash: PaymentHash, keys: Keypair, - ) -> Result { - let amount_msats = refund.amount_msats(); - let signing_pubkey = keys.public_key(); - let contents = InvoiceContents::ForRefund { - refund: refund.contents.clone(), - fields: Self::fields( - payment_paths, created_at, payment_hash, amount_msats, signing_pubkey - ), - }; - - Self::new(&refund.bytes, contents, DerivedSigningPubkey(keys)) - } + }; +} - /// Builds a signed [`Bolt12Invoice`] after checking for valid semantics. - pub fn build_and_sign( - $self: $self_type, secp_ctx: &Secp256k1 - ) -> Result { - #[cfg(feature = "std")] { - if $self.invoice.is_offer_or_refund_expired() { - return Err(Bolt12SemanticError::AlreadyExpired); +macro_rules! invoice_derived_signing_pubkey_builder_methods { + ($self: ident, $self_type: ty) => { + #[cfg_attr(c_bindings, allow(dead_code))] + pub(super) fn for_offer_using_keys( + invoice_request: &'a InvoiceRequest, payment_paths: Vec, + created_at: Duration, payment_hash: PaymentHash, keys: Keypair, + ) -> Result { + let amount_msats = Self::amount_msats(invoice_request)?; + let signing_pubkey = keys.public_key(); + let contents = InvoiceContents::ForOffer { + invoice_request: invoice_request.contents.clone(), + fields: Self::fields( + payment_paths, + created_at, + payment_hash, + amount_msats, + signing_pubkey, + ), + }; + + Self::new(&invoice_request.bytes, contents, DerivedSigningPubkey(keys)) + } + + #[cfg_attr(c_bindings, allow(dead_code))] + pub(super) fn for_refund_using_keys( + refund: &'a Refund, payment_paths: Vec, created_at: Duration, + payment_hash: PaymentHash, keys: Keypair, + ) -> Result { + let amount_msats = refund.amount_msats(); + let signing_pubkey = keys.public_key(); + let contents = InvoiceContents::ForRefund { + refund: refund.contents.clone(), + fields: Self::fields( + payment_paths, + created_at, + payment_hash, + amount_msats, + signing_pubkey, + ), + }; + + Self::new(&refund.bytes, contents, DerivedSigningPubkey(keys)) + } + + /// Builds a signed [`Bolt12Invoice`] after checking for valid semantics. + pub fn build_and_sign( + $self: $self_type, secp_ctx: &Secp256k1, + ) -> Result { + #[cfg(feature = "std")] + { + 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()) { - return Err(Bolt12SemanticError::AlreadyExpired); + #[cfg(not(feature = "std"))] + { + if $self.invoice.is_offer_or_refund_expired_no_std($self.invoice.created_at()) { + return Err(Bolt12SemanticError::AlreadyExpired); + } } - } - let Self { - invreq_bytes, invoice, signing_pubkey_strategy: DerivedSigningPubkey(keys) - } = $self; - #[cfg(not(c_bindings))] - let unsigned_invoice = UnsignedBolt12Invoice::new(invreq_bytes, invoice); - #[cfg(c_bindings)] - let mut unsigned_invoice = UnsignedBolt12Invoice::new(invreq_bytes, invoice.clone()); + let Self { invreq_bytes, invoice, signing_pubkey_strategy: DerivedSigningPubkey(keys) } = + $self; + #[cfg(not(c_bindings))] + let unsigned_invoice = UnsignedBolt12Invoice::new(invreq_bytes, invoice); + #[cfg(c_bindings)] + let mut unsigned_invoice = UnsignedBolt12Invoice::new(invreq_bytes, invoice.clone()); - let invoice = unsigned_invoice - .sign(|message: &UnsignedBolt12Invoice| - Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) - .unwrap(); - Ok(invoice) - } -} } + let invoice = unsigned_invoice + .sign(|message: &UnsignedBolt12Invoice| { + Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) + }) + .unwrap(); + Ok(invoice) + } + }; +} -macro_rules! invoice_builder_methods { ( +macro_rules! invoice_builder_methods { + ( $self: ident, $self_type: ty, $return_type: ty, $return_value: expr, $type_param: ty $(, $self_mut: tt)? ) => { - pub(crate) fn amount_msats( - invoice_request: &InvoiceRequest - ) -> Result { - match invoice_request.contents.inner.amount_msats() { - Some(amount_msats) => Ok(amount_msats), - None => match invoice_request.contents.inner.offer.amount() { - Some(Amount::Bitcoin { amount_msats }) => { - amount_msats.checked_mul(invoice_request.quantity().unwrap_or(1)) - .ok_or(Bolt12SemanticError::InvalidAmount) + pub(crate) fn amount_msats( + invoice_request: &InvoiceRequest, + ) -> Result { + match invoice_request.contents.inner.amount_msats() { + Some(amount_msats) => Ok(amount_msats), + None => match invoice_request.contents.inner.offer.amount() { + Some(Amount::Bitcoin { amount_msats }) => amount_msats + .checked_mul(invoice_request.quantity().unwrap_or(1)) + .ok_or(Bolt12SemanticError::InvalidAmount), + Some(Amount::Currency { .. }) => Err(Bolt12SemanticError::UnsupportedCurrency), + None => Err(Bolt12SemanticError::MissingAmount), }, - Some(Amount::Currency { .. }) => Err(Bolt12SemanticError::UnsupportedCurrency), - None => Err(Bolt12SemanticError::MissingAmount), - }, + } } - } - #[cfg_attr(c_bindings, allow(dead_code))] - fn fields( - payment_paths: Vec, created_at: Duration, payment_hash: PaymentHash, - amount_msats: u64, signing_pubkey: PublicKey - ) -> InvoiceFields { - InvoiceFields { - payment_paths, created_at, relative_expiry: None, payment_hash, amount_msats, - fallbacks: None, features: Bolt12InvoiceFeatures::empty(), signing_pubkey, - #[cfg(test)] - experimental_baz: None, + #[cfg_attr(c_bindings, allow(dead_code))] + fn fields( + payment_paths: Vec, created_at: Duration, + payment_hash: PaymentHash, amount_msats: u64, signing_pubkey: PublicKey, + ) -> InvoiceFields { + InvoiceFields { + payment_paths, + created_at, + relative_expiry: None, + payment_hash, + amount_msats, + fallbacks: None, + features: Bolt12InvoiceFeatures::empty(), + signing_pubkey, + #[cfg(test)] + experimental_baz: None, + } } - } - #[cfg_attr(c_bindings, allow(dead_code))] - fn new( - invreq_bytes: &'a Vec, contents: InvoiceContents, signing_pubkey_strategy: $type_param - ) -> Result { - if contents.fields().payment_paths.is_empty() { - return Err(Bolt12SemanticError::MissingPaths); - } + #[cfg_attr(c_bindings, allow(dead_code))] + fn new( + invreq_bytes: &'a Vec, contents: InvoiceContents, + signing_pubkey_strategy: $type_param, + ) -> Result { + if contents.fields().payment_paths.is_empty() { + return Err(Bolt12SemanticError::MissingPaths); + } - Ok(Self { invreq_bytes, invoice: contents, signing_pubkey_strategy }) - } -} } + Ok(Self { invreq_bytes, invoice: contents, signing_pubkey_strategy }) + } + }; +} #[cfg(test)] macro_rules! invoice_builder_methods_test { ( @@ -404,7 +465,15 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> { impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> { invoice_builder_methods!(self, Self, Self, self, S, mut); - invoice_builder_methods_common!(self, Self, self.invoice.fields_mut(), Self, self, Bolt12Invoice, mut); + invoice_builder_methods_common!( + self, + Self, + self.invoice.fields_mut(), + Self, + self, + Bolt12Invoice, + mut + ); #[cfg(test)] invoice_builder_methods_test!(self, Self, Self, self, mut); @@ -416,59 +485,101 @@ impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> { impl<'a> InvoiceWithExplicitSigningPubkeyBuilder<'a> { invoice_explicit_signing_pubkey_builder_methods!(self, &mut Self); invoice_builder_methods!(self, &mut Self, (), (), ExplicitSigningPubkey); - invoice_builder_methods_common!(self, &mut Self, self.invoice.fields_mut(), (), (), Bolt12Invoice); + invoice_builder_methods_common!( + self, + &mut Self, + self.invoice.fields_mut(), + (), + (), + Bolt12Invoice + ); } #[cfg(all(c_bindings, test))] impl<'a> InvoiceWithExplicitSigningPubkeyBuilder<'a> { invoice_explicit_signing_pubkey_builder_methods!(self, &mut Self); invoice_builder_methods!(self, &mut Self, &mut Self, self, ExplicitSigningPubkey); - invoice_builder_methods_common!(self, &mut Self, self.invoice.fields_mut(), &mut Self, self, Bolt12Invoice); + invoice_builder_methods_common!( + self, + &mut Self, + self.invoice.fields_mut(), + &mut Self, + self, + Bolt12Invoice + ); invoice_builder_methods_test!(self, &mut Self, &mut Self, self); - invoice_builder_methods_test_common!(self, &mut Self, self.invoice.fields_mut(), &mut Self, self); + invoice_builder_methods_test_common!( + self, + &mut Self, + self.invoice.fields_mut(), + &mut Self, + self + ); } #[cfg(all(c_bindings, not(test)))] impl<'a> InvoiceWithDerivedSigningPubkeyBuilder<'a> { invoice_derived_signing_pubkey_builder_methods!(self, &mut Self); invoice_builder_methods!(self, &mut Self, (), (), DerivedSigningPubkey); - invoice_builder_methods_common!(self, &mut Self, self.invoice.fields_mut(), (), (), Bolt12Invoice); + invoice_builder_methods_common!( + self, + &mut Self, + self.invoice.fields_mut(), + (), + (), + Bolt12Invoice + ); } #[cfg(all(c_bindings, test))] impl<'a> InvoiceWithDerivedSigningPubkeyBuilder<'a> { invoice_derived_signing_pubkey_builder_methods!(self, &mut Self); invoice_builder_methods!(self, &mut Self, &mut Self, self, DerivedSigningPubkey); - invoice_builder_methods_common!(self, &mut Self, self.invoice.fields_mut(), &mut Self, self, Bolt12Invoice); + invoice_builder_methods_common!( + self, + &mut Self, + self.invoice.fields_mut(), + &mut Self, + self, + Bolt12Invoice + ); invoice_builder_methods_test!(self, &mut Self, &mut Self, self); - invoice_builder_methods_test_common!(self, &mut Self, self.invoice.fields_mut(), &mut Self, self); + invoice_builder_methods_test_common!( + self, + &mut Self, + self.invoice.fields_mut(), + &mut Self, + self + ); } #[cfg(c_bindings)] impl<'a> From> -for InvoiceBuilder<'a, ExplicitSigningPubkey> { + for InvoiceBuilder<'a, ExplicitSigningPubkey> +{ fn from(builder: InvoiceWithExplicitSigningPubkeyBuilder<'a>) -> Self { let InvoiceWithExplicitSigningPubkeyBuilder { - invreq_bytes, invoice, signing_pubkey_strategy, + invreq_bytes, + invoice, + signing_pubkey_strategy, } = builder; - Self { - invreq_bytes, invoice, signing_pubkey_strategy, - } + Self { invreq_bytes, invoice, signing_pubkey_strategy } } } #[cfg(c_bindings)] impl<'a> From> -for InvoiceBuilder<'a, DerivedSigningPubkey> { + for InvoiceBuilder<'a, DerivedSigningPubkey> +{ fn from(builder: InvoiceWithDerivedSigningPubkeyBuilder<'a>) -> Self { let InvoiceWithDerivedSigningPubkeyBuilder { - invreq_bytes, invoice, signing_pubkey_strategy, + invreq_bytes, + invoice, + signing_pubkey_strategy, } = builder; - Self { - invreq_bytes, invoice, signing_pubkey_strategy, - } + Self { invreq_bytes, invoice, signing_pubkey_strategy } } } @@ -537,8 +648,7 @@ impl UnsignedBolt12Invoice { const EXPERIMENTAL_TLV_ALLOCATION_SIZE: usize = 0; let mut experimental_bytes = Vec::with_capacity(EXPERIMENTAL_TLV_ALLOCATION_SIZE); - let experimental_tlv_stream = TlvStream::new(remaining_bytes) - .range(EXPERIMENTAL_TYPES); + let experimental_tlv_stream = TlvStream::new(remaining_bytes).range(EXPERIMENTAL_TYPES); for record in experimental_tlv_stream { record.write(&mut experimental_bytes).unwrap(); } @@ -636,17 +746,11 @@ enum InvoiceContents { /// Contents for an [`Bolt12Invoice`] corresponding to an [`Offer`]. /// /// [`Offer`]: crate::offers::offer::Offer - ForOffer { - invoice_request: InvoiceRequestContents, - fields: InvoiceFields, - }, + ForOffer { invoice_request: InvoiceRequestContents, fields: InvoiceFields }, /// Contents for an [`Bolt12Invoice`] corresponding to a [`Refund`]. /// /// [`Refund`]: crate::offers::refund::Refund - ForRefund { - refund: RefundContents, - fields: InvoiceFields, - }, + ForRefund { refund: RefundContents, fields: InvoiceFields }, } /// Invoice-specific fields for an `invoice` message. @@ -868,7 +972,7 @@ impl Bolt12Invoice { /// /// Returns the associated [`PaymentId`] to use when sending the payment. pub fn verify_using_metadata( - &self, key: &ExpandedKey, secp_ctx: &Secp256k1 + &self, key: &ExpandedKey, secp_ctx: &Secp256k1, ) -> Result { let (metadata, iv_bytes) = match &self.contents { InvoiceContents::ForOffer { invoice_request, .. } => { @@ -885,34 +989,40 @@ impl Bolt12Invoice { /// checking a payment id and nonce included with the [`BlindedMessagePath`] for which the invoice was /// sent through. pub fn verify_using_payer_data( - &self, payment_id: PaymentId, nonce: Nonce, key: &ExpandedKey, secp_ctx: &Secp256k1 + &self, payment_id: PaymentId, nonce: Nonce, key: &ExpandedKey, secp_ctx: &Secp256k1, ) -> Result { let metadata = Metadata::payer_data(payment_id, nonce, key); let iv_bytes = match &self.contents { InvoiceContents::ForOffer { .. } => INVOICE_REQUEST_IV_BYTES, InvoiceContents::ForRefund { .. } => REFUND_IV_BYTES_WITHOUT_METADATA, }; - self.contents - .verify(&self.bytes, &metadata, key, iv_bytes, secp_ctx) - .and_then(|extracted_payment_id| (payment_id == extracted_payment_id) - .then(|| payment_id) - .ok_or(()) - ) + self.contents.verify(&self.bytes, &metadata, key, iv_bytes, secp_ctx).and_then( + |extracted_payment_id| { + (payment_id == extracted_payment_id).then(|| payment_id).ok_or(()) + }, + ) } pub(crate) fn as_tlv_stream(&self) -> FullInvoiceTlvStreamRef { let ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream, - experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + invoice_tlv_stream, + experimental_offer_tlv_stream, + experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream, ) = self.contents.as_tlv_stream(); - let signature_tlv_stream = SignatureTlvStreamRef { - signature: Some(&self.signature), - }; + let signature_tlv_stream = SignatureTlvStreamRef { signature: Some(&self.signature) }; ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream, - signature_tlv_stream, experimental_offer_tlv_stream, - experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream, + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + invoice_tlv_stream, + signature_tlv_stream, + experimental_offer_tlv_stream, + experimental_invoice_request_tlv_stream, + experimental_invoice_tlv_stream, ) } @@ -943,8 +1053,9 @@ impl InvoiceContents { #[cfg(feature = "std")] fn is_offer_or_refund_expired(&self) -> bool { match self { - InvoiceContents::ForOffer { invoice_request, .. } => - invoice_request.inner.offer.is_expired(), + InvoiceContents::ForOffer { invoice_request, .. } => { + invoice_request.inner.offer.is_expired() + }, InvoiceContents::ForRefund { refund, .. } => refund.is_expired(), } } @@ -952,17 +1063,20 @@ impl InvoiceContents { #[cfg(not(feature = "std"))] fn is_offer_or_refund_expired_no_std(&self, duration_since_epoch: Duration) -> bool { match self { - InvoiceContents::ForOffer { invoice_request, .. } => - invoice_request.inner.offer.is_expired_no_std(duration_since_epoch), - InvoiceContents::ForRefund { refund, .. } => - refund.is_expired_no_std(duration_since_epoch), + InvoiceContents::ForOffer { invoice_request, .. } => { + invoice_request.inner.offer.is_expired_no_std(duration_since_epoch) + }, + InvoiceContents::ForRefund { refund, .. } => { + refund.is_expired_no_std(duration_since_epoch) + }, } } fn offer_chains(&self) -> Option> { match self { - InvoiceContents::ForOffer { invoice_request, .. } => - Some(invoice_request.inner.offer.chains()), + InvoiceContents::ForOffer { invoice_request, .. } => { + Some(invoice_request.inner.offer.chains()) + }, InvoiceContents::ForRefund { .. } => None, } } @@ -976,16 +1090,18 @@ impl InvoiceContents { fn metadata(&self) -> Option<&Vec> { match self { - InvoiceContents::ForOffer { invoice_request, .. } => - invoice_request.inner.offer.metadata(), + InvoiceContents::ForOffer { invoice_request, .. } => { + invoice_request.inner.offer.metadata() + }, InvoiceContents::ForRefund { .. } => None, } } fn amount(&self) -> Option { match self { - InvoiceContents::ForOffer { invoice_request, .. } => - invoice_request.inner.offer.amount(), + InvoiceContents::ForOffer { invoice_request, .. } => { + invoice_request.inner.offer.amount() + }, InvoiceContents::ForRefund { .. } => None, } } @@ -1076,7 +1192,9 @@ impl InvoiceContents { fn payer_signing_pubkey(&self) -> PublicKey { match self { - InvoiceContents::ForOffer { invoice_request, .. } => invoice_request.payer_signing_pubkey(), + InvoiceContents::ForOffer { invoice_request, .. } => { + invoice_request.payer_signing_pubkey() + }, InvoiceContents::ForRefund { refund, .. } => refund.payer_signing_pubkey(), } } @@ -1114,7 +1232,8 @@ impl InvoiceContents { } fn fallbacks(&self) -> Vec
{ - self.fields().fallbacks + self.fields() + .fallbacks .as_ref() .map(|fallbacks| filter_fallbacks(self.chain(), fallbacks)) .unwrap_or_default() @@ -1162,22 +1281,33 @@ impl InvoiceContents { let signing_pubkey = self.payer_signing_pubkey(); signer::verify_payer_metadata( - metadata.as_ref(), key, iv_bytes, signing_pubkey, tlv_stream, secp_ctx, + metadata.as_ref(), + key, + iv_bytes, + signing_pubkey, + tlv_stream, + secp_ctx, ) } fn as_tlv_stream(&self) -> PartialInvoiceTlvStreamRef { - let ( - payer, offer, invoice_request, experimental_offer, experimental_invoice_request, - ) = match self { - InvoiceContents::ForOffer { invoice_request, .. } => invoice_request.as_tlv_stream(), - InvoiceContents::ForRefund { refund, .. } => refund.as_tlv_stream(), - }; + let (payer, offer, invoice_request, experimental_offer, experimental_invoice_request) = + match self { + InvoiceContents::ForOffer { invoice_request, .. } => { + invoice_request.as_tlv_stream() + }, + InvoiceContents::ForRefund { refund, .. } => refund.as_tlv_stream(), + }; let (invoice, experimental_invoice) = self.fields().as_tlv_stream(); ( - payer, offer, invoice_request, invoice, experimental_offer, - experimental_invoice_request, experimental_invoice, + payer, + offer, + invoice_request, + invoice, + experimental_offer, + experimental_invoice_request, + experimental_invoice, ) } } @@ -1194,9 +1324,7 @@ pub(super) fn is_expired(created_at: Duration, relative_expiry: Duration) -> boo } } -pub(super) fn filter_fallbacks( - chain: ChainHash, fallbacks: &Vec -) -> Vec
{ +pub(super) fn filter_fallbacks(chain: ChainHash, fallbacks: &Vec) -> Vec
{ let network = if chain == ChainHash::using_genesis_block(Network::Bitcoin) { Network::Bitcoin } else if chain == ChainHash::using_genesis_block(Network::Testnet) { @@ -1206,7 +1334,7 @@ pub(super) fn filter_fallbacks( } else if chain == ChainHash::using_genesis_block(Network::Regtest) { Network::Regtest } else { - return Vec::new() + return Vec::new(); }; let to_valid_address = |address: &FallbackAddress| { @@ -1228,13 +1356,18 @@ pub(super) fn filter_fallbacks( impl InvoiceFields { fn as_tlv_stream(&self) -> (InvoiceTlvStreamRef, ExperimentalInvoiceTlvStreamRef) { let features = { - if self.features == Bolt12InvoiceFeatures::empty() { None } - else { Some(&self.features) } + if self.features == Bolt12InvoiceFeatures::empty() { + None + } else { + Some(&self.features) + } }; ( InvoiceTlvStreamRef { - paths: Some(Iterable(self.payment_paths.iter().map(|path| path.inner_blinded_path()))), + paths: Some(Iterable( + self.payment_paths.iter().map(|path| path.inner_blinded_path()), + )), blindedpay: Some(Iterable(self.payment_paths.iter().map(|path| &path.payinfo))), created_at: Some(self.created_at.as_secs()), relative_expiry: self.relative_expiry.map(|duration| duration.as_secs() as u32), @@ -1329,7 +1462,10 @@ pub(super) const EXPERIMENTAL_INVOICE_TYPES: core::ops::RangeFrom = 3_000_0 #[cfg(not(test))] tlv_stream!( - ExperimentalInvoiceTlvStream, ExperimentalInvoiceTlvStreamRef, EXPERIMENTAL_INVOICE_TYPES, { + ExperimentalInvoiceTlvStream, + ExperimentalInvoiceTlvStreamRef, + EXPERIMENTAL_INVOICE_TYPES, + { // When adding experimental TLVs, update EXPERIMENTAL_TLV_ALLOCATION_SIZE accordingly in // both UnsignedBolt12Invoice:new and UnsignedStaticInvoice::new to avoid unnecessary // allocations. @@ -1362,9 +1498,15 @@ pub(super) struct FallbackAddress { impl_writeable!(FallbackAddress, { version, program }); -type FullInvoiceTlvStream =( - PayerTlvStream, OfferTlvStream, InvoiceRequestTlvStream, InvoiceTlvStream, SignatureTlvStream, - ExperimentalOfferTlvStream, ExperimentalInvoiceRequestTlvStream, ExperimentalInvoiceTlvStream, +type FullInvoiceTlvStream = ( + PayerTlvStream, + OfferTlvStream, + InvoiceRequestTlvStream, + InvoiceTlvStream, + SignatureTlvStream, + ExperimentalOfferTlvStream, + ExperimentalInvoiceRequestTlvStream, + ExperimentalInvoiceTlvStream, ); type FullInvoiceTlvStreamRef<'a> = ( @@ -1389,18 +1531,27 @@ impl CursorReadable for FullInvoiceTlvStream { let experimental_invoice_request = CursorReadable::read(r)?; let experimental_invoice = CursorReadable::read(r)?; - Ok( - ( - payer, offer, invoice_request, invoice, signature, experimental_offer, - experimental_invoice_request, experimental_invoice, - ) - ) + Ok(( + payer, + offer, + invoice_request, + invoice, + signature, + experimental_offer, + experimental_invoice_request, + experimental_invoice, + )) } } type PartialInvoiceTlvStream = ( - PayerTlvStream, OfferTlvStream, InvoiceRequestTlvStream, InvoiceTlvStream, - ExperimentalOfferTlvStream, ExperimentalInvoiceRequestTlvStream, ExperimentalInvoiceTlvStream, + PayerTlvStream, + OfferTlvStream, + InvoiceRequestTlvStream, + InvoiceTlvStream, + ExperimentalOfferTlvStream, + ExperimentalInvoiceRequestTlvStream, + ExperimentalInvoiceTlvStream, ); type PartialInvoiceTlvStreamRef<'a> = ( @@ -1423,12 +1574,15 @@ impl CursorReadable for PartialInvoiceTlvStream { let experimental_invoice_request = CursorReadable::read(r)?; let experimental_invoice = CursorReadable::read(r)?; - Ok( - ( - payer, offer, invoice_request, invoice, experimental_offer, - experimental_invoice_request, experimental_invoice, - ) - ) + Ok(( + payer, + offer, + invoice_request, + invoice, + experimental_offer, + experimental_invoice_request, + experimental_invoice, + )) } } @@ -1438,23 +1592,27 @@ impl TryFrom> for Bolt12Invoice { fn try_from(invoice: ParsedMessage) -> Result { let ParsedMessage { bytes, tlv_stream } = invoice; let ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream, + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + invoice_tlv_stream, SignatureTlvStream { signature }, experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream, ) = tlv_stream; - let contents = InvoiceContents::try_from( - ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream, - experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, - experimental_invoice_tlv_stream, - ) - )?; + let contents = InvoiceContents::try_from(( + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + invoice_tlv_stream, + experimental_offer_tlv_stream, + experimental_invoice_request_tlv_stream, + experimental_invoice_tlv_stream, + ))?; - let signature = signature.ok_or( - Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature) - )?; + let signature = signature + .ok_or(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature))?; let tagged_hash = TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &bytes); let pubkey = contents.fields().signing_pubkey; merkle::verify_signature(&signature, &tagged_hash, pubkey)?; @@ -1472,8 +1630,16 @@ impl TryFrom for InvoiceContents { offer_tlv_stream, invoice_request_tlv_stream, InvoiceTlvStream { - paths, blindedpay, created_at, relative_expiry, payment_hash, amount, fallbacks, - features, node_id, message_paths, + paths, + blindedpay, + created_at, + relative_expiry, + payment_hash, + amount, + fallbacks, + features, + node_id, + message_paths, }, experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, @@ -1483,7 +1649,9 @@ impl TryFrom for InvoiceContents { }, ) = tlv_stream; - if message_paths.is_some() { return Err(Bolt12SemanticError::UnexpectedPaths) } + if message_paths.is_some() { + return Err(Bolt12SemanticError::UnexpectedPaths); + } let payment_paths = construct_payment_paths(blindedpay, paths)?; @@ -1492,9 +1660,7 @@ impl TryFrom for InvoiceContents { Some(timestamp) => Duration::from_secs(timestamp), }; - let relative_expiry = relative_expiry - .map(Into::::into) - .map(Duration::from_secs); + let relative_expiry = relative_expiry.map(Into::::into).map(Duration::from_secs); let payment_hash = payment_hash.ok_or(Bolt12SemanticError::MissingPaymentHash)?; @@ -1505,8 +1671,14 @@ impl TryFrom for InvoiceContents { let signing_pubkey = node_id.ok_or(Bolt12SemanticError::MissingSigningPubkey)?; let fields = InvoiceFields { - payment_paths, created_at, relative_expiry, payment_hash, amount_msats, fallbacks, - features, signing_pubkey, + payment_paths, + created_at, + relative_expiry, + payment_hash, + amount_msats, + fallbacks, + features, + signing_pubkey, #[cfg(test)] experimental_baz, }; @@ -1514,12 +1686,13 @@ impl TryFrom for InvoiceContents { check_invoice_signing_pubkey(&fields.signing_pubkey, &offer_tlv_stream)?; if offer_tlv_stream.issuer_id.is_none() && offer_tlv_stream.paths.is_none() { - let refund = RefundContents::try_from( - ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, - experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, - ) - )?; + let refund = RefundContents::try_from(( + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + experimental_offer_tlv_stream, + experimental_invoice_request_tlv_stream, + ))?; if amount_msats != refund.amount_msats() { return Err(Bolt12SemanticError::InvalidAmount); @@ -1527,12 +1700,13 @@ impl TryFrom for InvoiceContents { Ok(InvoiceContents::ForRefund { refund, fields }) } else { - let invoice_request = InvoiceRequestContents::try_from( - ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, - experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, - ) - )?; + let invoice_request = InvoiceRequestContents::try_from(( + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + experimental_offer_tlv_stream, + experimental_invoice_request_tlv_stream, + ))?; if let Some(requested_amount_msats) = invoice_request.amount_msats() { if amount_msats != requested_amount_msats { @@ -1546,7 +1720,7 @@ impl TryFrom for InvoiceContents { } pub(super) fn construct_payment_paths( - blinded_payinfos: Option>, blinded_paths: Option> + blinded_payinfos: Option>, blinded_paths: Option>, ) -> Result, Bolt12SemanticError> { match (blinded_payinfos, blinded_paths) { (_, None) => Err(Bolt12SemanticError::MissingPaths), @@ -1555,19 +1729,16 @@ pub(super) fn construct_payment_paths( (Some(blindedpay), Some(paths)) if paths.len() != blindedpay.len() => { Err(Bolt12SemanticError::InvalidPayInfo) }, - (Some(blindedpay), Some(paths)) => { - Ok(blindedpay - .into_iter() - .zip(paths.into_iter()) - .map(|(payinfo, path)| BlindedPaymentPath::from_parts(path, payinfo)) - .collect::>() - ) - }, + (Some(blindedpay), Some(paths)) => Ok(blindedpay + .into_iter() + .zip(paths.into_iter()) + .map(|(payinfo, path)| BlindedPaymentPath::from_parts(path, payinfo)) + .collect::>()), } } pub(super) fn check_invoice_signing_pubkey( - invoice_signing_pubkey: &PublicKey, offer_tlv_stream: &OfferTlvStream + invoice_signing_pubkey: &PublicKey, offer_tlv_stream: &OfferTlvStream, ) -> Result<(), Bolt12SemanticError> { match (&offer_tlv_stream.issuer_id, &offer_tlv_stream.paths) { (Some(issuer_signing_pubkey), _) => { @@ -1591,45 +1762,50 @@ pub(super) fn check_invoice_signing_pubkey( #[cfg(test)] mod tests { - use super::{Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, EXPERIMENTAL_INVOICE_TYPES, ExperimentalInvoiceTlvStreamRef, FallbackAddress, FullInvoiceTlvStreamRef, INVOICE_TYPES, InvoiceTlvStreamRef, SIGNATURE_TAG, UnsignedBolt12Invoice}; + use super::{ + Bolt12Invoice, ExperimentalInvoiceTlvStreamRef, FallbackAddress, FullInvoiceTlvStreamRef, + InvoiceTlvStreamRef, UnsignedBolt12Invoice, DEFAULT_RELATIVE_EXPIRY, + EXPERIMENTAL_INVOICE_TYPES, INVOICE_TYPES, SIGNATURE_TAG, + }; - use bitcoin::{CompressedPublicKey, WitnessProgram, WitnessVersion}; + use bitcoin::address::Address; use bitcoin::constants::ChainHash; - use bitcoin::script::ScriptBuf; use bitcoin::hashes::Hash; - use bitcoin::network::Network; - use bitcoin::secp256k1::{Keypair, Message, Secp256k1, SecretKey, XOnlyPublicKey, self}; - use bitcoin::address::Address; use bitcoin::key::TweakedPublicKey; + use bitcoin::network::Network; + use bitcoin::script::ScriptBuf; + use bitcoin::secp256k1::{self, Keypair, Message, Secp256k1, SecretKey, XOnlyPublicKey}; + use bitcoin::{CompressedPublicKey, WitnessProgram, WitnessVersion}; use core::time::Duration; - use crate::blinded_path::BlindedHop; use crate::blinded_path::message::BlindedMessagePath; - use crate::types::features::{Bolt12InvoiceFeatures, InvoiceRequestFeatures, OfferFeatures}; + use crate::blinded_path::BlindedHop; use crate::ln::channelmanager::PaymentId; use crate::ln::inbound_payment::ExpandedKey; use crate::ln::msgs::DecodeError; - use crate::offers::invoice_request::{ExperimentalInvoiceRequestTlvStreamRef, InvoiceRequestTlvStreamRef}; - use crate::offers::merkle::{SignError, SignatureTlvStreamRef, TaggedHash, TlvStream, self}; + use crate::offers::invoice_request::{ + ExperimentalInvoiceRequestTlvStreamRef, InvoiceRequestTlvStreamRef, + }; + use crate::offers::merkle::{self, SignError, SignatureTlvStreamRef, TaggedHash, TlvStream}; use crate::offers::nonce::Nonce; - use crate::offers::offer::{Amount, ExperimentalOfferTlvStreamRef, OfferTlvStreamRef, Quantity}; + use crate::offers::offer::{ + Amount, ExperimentalOfferTlvStreamRef, OfferTlvStreamRef, Quantity, + }; + use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError}; + use crate::offers::payer::PayerTlvStreamRef; + use crate::offers::test_utils::*; use crate::prelude::*; + use crate::types::features::{Bolt12InvoiceFeatures, InvoiceRequestFeatures, OfferFeatures}; + use crate::util::ser::{BigSize, Iterable, Writeable}; + use crate::util::string::PrintableString; #[cfg(not(c_bindings))] - use { - crate::offers::offer::OfferBuilder, - crate::offers::refund::RefundBuilder, - }; + use {crate::offers::offer::OfferBuilder, crate::offers::refund::RefundBuilder}; #[cfg(c_bindings)] use { crate::offers::offer::OfferWithExplicitMetadataBuilder as OfferBuilder, crate::offers::refund::RefundMaybeWithDerivedMetadataBuilder as RefundBuilder, }; - use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError}; - use crate::offers::payer::PayerTlvStreamRef; - use crate::offers::test_utils::*; - use crate::util::ser::{BigSize, Iterable, Writeable}; - use crate::util::string::PrintableString; trait ToBytes { fn to_bytes(&self) -> Vec; @@ -1661,18 +1837,26 @@ mod tests { let now = now(); let unsigned_invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths.clone(), payment_hash, now).unwrap() - .build().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths.clone(), payment_hash, now) + .unwrap() + .build() + .unwrap(); let mut buffer = Vec::new(); unsigned_invoice.write(&mut buffer).unwrap(); assert_eq!(unsigned_invoice.bytes, buffer.as_slice()); assert_eq!(unsigned_invoice.payer_metadata(), &encrypted_payment_id); - assert_eq!(unsigned_invoice.offer_chains(), Some(vec![ChainHash::using_genesis_block(Network::Bitcoin)])); + assert_eq!( + unsigned_invoice.offer_chains(), + Some(vec![ChainHash::using_genesis_block(Network::Bitcoin)]) + ); assert_eq!(unsigned_invoice.metadata(), None); assert_eq!(unsigned_invoice.amount(), Some(Amount::Bitcoin { amount_msats: 1000 })); assert_eq!(unsigned_invoice.description(), Some(PrintableString(""))); @@ -1713,7 +1897,10 @@ mod tests { assert_eq!(invoice.bytes, buffer.as_slice()); assert_eq!(invoice.payer_metadata(), &encrypted_payment_id); - assert_eq!(invoice.offer_chains(), Some(vec![ChainHash::using_genesis_block(Network::Bitcoin)])); + assert_eq!( + invoice.offer_chains(), + Some(vec![ChainHash::using_genesis_block(Network::Bitcoin)]) + ); assert_eq!(invoice.metadata(), None); assert_eq!(invoice.amount(), Some(Amount::Bitcoin { amount_msats: 1000 })); assert_eq!(invoice.description(), Some(PrintableString(""))); @@ -1778,7 +1965,9 @@ mod tests { offer_from_hrn: None, }, InvoiceTlvStreamRef { - paths: Some(Iterable(payment_paths.iter().map(|path| path.inner_blinded_path()))), + paths: Some(Iterable( + payment_paths.iter().map(|path| path.inner_blinded_path()) + )), blindedpay: Some(Iterable(payment_paths.iter().map(|path| &path.payinfo))), created_at: Some(now.as_secs()), relative_expiry: None, @@ -1790,15 +1979,9 @@ mod tests { message_paths: None, }, SignatureTlvStreamRef { signature: Some(&invoice.signature()) }, - ExperimentalOfferTlvStreamRef { - experimental_foo: None, - }, - ExperimentalInvoiceRequestTlvStreamRef { - experimental_bar: None, - }, - ExperimentalInvoiceTlvStreamRef { - experimental_baz: None, - }, + ExperimentalOfferTlvStreamRef { experimental_foo: None }, + ExperimentalInvoiceRequestTlvStreamRef { experimental_bar: None }, + ExperimentalInvoiceTlvStreamRef { experimental_baz: None }, ), ); @@ -1812,12 +1995,16 @@ mod tests { let payment_paths = payment_paths(); let payment_hash = payment_hash(); let now = now(); - let invoice = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap() + let invoice = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() + .build() + .unwrap() .respond_with_no_std(payment_paths.clone(), payment_hash, recipient_pubkey(), now) .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -1881,7 +2068,9 @@ mod tests { offer_from_hrn: None, }, InvoiceTlvStreamRef { - paths: Some(Iterable(payment_paths.iter().map(|path| path.inner_blinded_path()))), + paths: Some(Iterable( + payment_paths.iter().map(|path| path.inner_blinded_path()) + )), blindedpay: Some(Iterable(payment_paths.iter().map(|path| &path.payinfo))), created_at: Some(now.as_secs()), relative_expiry: None, @@ -1893,15 +2082,9 @@ mod tests { message_paths: None, }, SignatureTlvStreamRef { signature: Some(&invoice.signature()) }, - ExperimentalOfferTlvStreamRef { - experimental_foo: None, - }, - ExperimentalInvoiceRequestTlvStreamRef { - experimental_bar: None, - }, - ExperimentalInvoiceTlvStreamRef { - experimental_baz: None, - }, + ExperimentalOfferTlvStreamRef { experimental_foo: None }, + ExperimentalInvoiceRequestTlvStreamRef { experimental_bar: None }, + ExperimentalInvoiceTlvStreamRef { experimental_baz: None }, ), ); @@ -1925,9 +2108,12 @@ mod tests { if let Err(e) = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .absolute_expiry(future_expiry) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() .respond_with(payment_paths(), payment_hash()) .unwrap() .build() @@ -1938,8 +2124,10 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .absolute_expiry(past_expiry) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_unchecked_and_sign() .respond_with(payment_paths(), payment_hash()) .unwrap() @@ -1956,9 +2144,11 @@ mod tests { let future_expiry = Duration::from_secs(u64::max_value()); let past_expiry = Duration::from_secs(0); - if let Err(e) = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + if let Err(e) = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .absolute_expiry(future_expiry) - .build().unwrap() + .build() + .unwrap() .respond_with(payment_paths(), payment_hash(), recipient_pubkey()) .unwrap() .build() @@ -1966,9 +2156,11 @@ mod tests { panic!("error building invoice: {:?}", e); } - match RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + match RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .absolute_expiry(past_expiry) - .build().unwrap() + .build() + .unwrap() .respond_with(payment_paths(), payment_hash(), recipient_pubkey()) .unwrap() .build() @@ -1988,48 +2180,59 @@ mod tests { let payment_id = PaymentId([1; 32]); let blinded_path = BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(42), encrypted_payload: vec![0; 43] }, BlindedHop { blinded_node_id: node_id, encrypted_payload: vec![0; 44] }, - ] + ], ); #[cfg(c_bindings)] use crate::offers::offer::OfferWithDerivedMetadataBuilder as OfferBuilder; - let invoice_request = OfferBuilder - ::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx) - .amount_msats(1000) - .path(blinded_path) - .experimental_foo(42) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); - - if let Err(e) = invoice_request.clone() - .verify_using_recipient_data(nonce, &expanded_key, &secp_ctx).unwrap() - .respond_using_derived_keys_no_std(payment_paths(), payment_hash(), now()).unwrap() + let invoice_request = + OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx) + .amount_msats(1000) + .path(blinded_path) + .experimental_foo(42) + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); + + if let Err(e) = invoice_request + .clone() + .verify_using_recipient_data(nonce, &expanded_key, &secp_ctx) + .unwrap() + .respond_using_derived_keys_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .build_and_sign(&secp_ctx) { panic!("error building invoice: {:?}", e); } let expanded_key = ExpandedKey::new([41; 32]); - assert!( - invoice_request.verify_using_recipient_data(nonce, &expanded_key, &secp_ctx).is_err() - ); - - let invoice_request = OfferBuilder - ::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx) - .amount_msats(1000) - // Omit the path so that node_id is used for the signing pubkey instead of deriving it - .experimental_foo(42) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + assert!(invoice_request + .verify_using_recipient_data(nonce, &expanded_key, &secp_ctx) + .is_err()); + + let invoice_request = + OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx) + .amount_msats(1000) + // Omit the path so that node_id is used for the signing pubkey instead of deriving it + .experimental_foo(42) + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); match invoice_request - .verify_using_metadata(&expanded_key, &secp_ctx).unwrap() + .verify_using_metadata(&expanded_key, &secp_ctx) + .unwrap() .respond_using_derived_keys_no_std(payment_paths(), payment_hash(), now()) { Ok(_) => panic!("expected error"), @@ -2043,13 +2246,19 @@ mod tests { let entropy = FixedEntropy {}; let secp_ctx = Secp256k1::new(); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .experimental_foo(42) - .build().unwrap(); + .build() + .unwrap(); if let Err(e) = refund .respond_using_derived_keys_no_std( - payment_paths(), payment_hash(), now(), &expanded_key, &entropy + payment_paths(), + payment_hash(), + now(), + &expanded_key, + &entropy, ) .unwrap() .build_and_sign(&secp_ctx) @@ -2066,20 +2275,27 @@ mod tests { let secp_ctx = Secp256k1::new(); let blinded_path = BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(42), encrypted_payload: vec![0; 43] }, BlindedHop { blinded_node_id: node_id, encrypted_payload: vec![0; 44] }, - ] + ], ); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .path(blinded_path) - .build().unwrap(); + .build() + .unwrap(); let invoice = refund .respond_using_derived_keys_no_std( - payment_paths(), payment_hash(), now(), &expanded_key, &entropy + payment_paths(), + payment_hash(), + now(), + &expanded_key, + &entropy, ) .unwrap() .build_and_sign(&secp_ctx) @@ -2101,13 +2317,19 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now) + .unwrap() .relative_expiry(one_hour.as_secs() as u32) - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let (_, _, _, tlv_stream, _, _, _, _) = invoice.as_tlv_stream(); #[cfg(feature = "std")] assert!(!invoice.is_expired()); @@ -2116,15 +2338,21 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now - one_hour).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now - one_hour) + .unwrap() .relative_expiry(one_hour.as_secs() as u32 - 1) - .build().unwrap() - .sign(recipient_sign).unwrap(); - let (_, _, _, tlv_stream, _, _, _, _) = invoice.as_tlv_stream(); - #[cfg(feature = "std")] + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); + let (_, _, _, tlv_stream, _, _, _, _) = invoice.as_tlv_stream(); + #[cfg(feature = "std")] assert!(invoice.is_expired()); assert_eq!(invoice.relative_expiry(), one_hour - Duration::from_secs(1)); assert_eq!(tlv_stream.relative_expiry, Some(one_hour.as_secs() as u32 - 1)); @@ -2140,13 +2368,20 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(1001).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(1001) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let (_, _, _, tlv_stream, _, _, _, _) = invoice.as_tlv_stream(); assert_eq!(invoice.amount_msats(), 1001); assert_eq!(tlv_stream.amount, Some(1001)); @@ -2163,13 +2398,20 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .quantity(2).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .quantity(2) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let (_, _, _, tlv_stream, _, _, _, _) = invoice.as_tlv_stream(); assert_eq!(invoice.amount_msats(), 2000); assert_eq!(tlv_stream.amount, Some(2000)); @@ -2177,9 +2419,12 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .quantity(u64::max_value()).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .quantity(u64::max_value()) + .unwrap() .build_unchecked_and_sign() .respond_with_no_std(payment_paths(), payment_hash(), now()) { @@ -2203,15 +2448,21 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .fallback_v0_p2wsh(&script.wscript_hash()) .fallback_v0_p2wpkh(&pubkey.wpubkey_hash().unwrap()) .fallback_v1_p2tr_tweaked(&tweaked_pubkey) - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let (_, _, _, tlv_stream, _, _, _, _) = invoice.as_tlv_stream(); assert_eq!( invoice.fallbacks(), @@ -2253,13 +2504,19 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .allow_mpp() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let (_, _, _, tlv_stream, _, _, _, _) = invoice.as_tlv_stream(); assert_eq!(invoice.invoice_features(), &features); assert_eq!(tlv_stream.features, Some(&features)); @@ -2275,11 +2532,16 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() .sign(fail_sign) { Ok(_) => panic!("expected error"), @@ -2288,11 +2550,16 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() .sign(payer_sign) { Ok(_) => panic!("expected error"), @@ -2310,12 +2577,18 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -2329,7 +2602,9 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaths)), + Err(e) => { + assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaths)) + }, } let mut tlv_stream = invoice.as_tlv_stream(); @@ -2337,16 +2612,22 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidPayInfo)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidPayInfo) + ), } let empty_payment_paths = vec![]; let mut tlv_stream = invoice.as_tlv_stream(); - tlv_stream.3.paths = Some(Iterable(empty_payment_paths.iter().map(|path| path.inner_blinded_path()))); + tlv_stream.3.paths = + Some(Iterable(empty_payment_paths.iter().map(|path| path.inner_blinded_path()))); match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaths)), + Err(e) => { + assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaths)) + }, } let mut payment_paths = payment_paths(); @@ -2356,7 +2637,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidPayInfo)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidPayInfo) + ), } } @@ -2370,12 +2654,18 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -2390,7 +2680,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingCreationTime)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingCreationTime) + ); }, } } @@ -2405,13 +2698,19 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .relative_expiry(3600) - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -2432,12 +2731,18 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -2452,7 +2757,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaymentHash)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaymentHash) + ); }, } } @@ -2467,12 +2775,18 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -2486,7 +2800,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount) + ), } } @@ -2500,13 +2817,19 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .allow_mpp() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -2536,15 +2859,18 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); #[cfg(not(c_bindings))] - let invoice_builder = invoice_request - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap(); + let invoice_builder = + invoice_request.respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap(); #[cfg(c_bindings)] - let mut invoice_builder = invoice_request - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap(); + let mut invoice_builder = + invoice_request.respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap(); let invoice_builder = invoice_builder .fallback_v0_p2wsh(&script.wscript_hash()) .fallback_v0_p2wpkh(&pubkey.wpubkey_hash().unwrap()) @@ -2568,8 +2894,10 @@ mod tests { match Bolt12Invoice::try_from(buffer) { Ok(invoice) => { - let v1_witness_program = WitnessProgram::new(WitnessVersion::V1, &[0u8; 33]).unwrap(); - let v2_witness_program = WitnessProgram::new(WitnessVersion::V2, &[0u8; 40]).unwrap(); + let v1_witness_program = + WitnessProgram::new(WitnessVersion::V1, &[0u8; 33]).unwrap(); + let v2_witness_program = + WitnessProgram::new(WitnessVersion::V2, &[0u8; 40]).unwrap(); assert_eq!( invoice.fallbacks(), vec![ @@ -2595,12 +2923,18 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -2615,7 +2949,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSigningPubkey) + ); }, } @@ -2626,7 +2963,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidSigningPubkey)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidSigningPubkey) + ); }, } } @@ -2641,24 +2981,27 @@ mod tests { let paths = vec![ BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] }, BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] }, - ] + ], ), BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] }, BlindedHop { blinded_node_id: pubkey(46), encrypted_payload: vec![0; 46] }, - ] + ], ), ]; let blinded_node_id_sign = |message: &UnsignedBolt12Invoice| { let secp_ctx = Secp256k1::new(); - let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[46; 32]).unwrap()); + let keys = + Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[46; 32]).unwrap()); Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) }; @@ -2667,14 +3010,23 @@ mod tests { .amount_msats(1000) .path(paths[0].clone()) .path(paths[1].clone()) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() .respond_with_no_std_using_signing_pubkey( - payment_paths(), payment_hash(), now(), pubkey(46) - ).unwrap() - .build().unwrap() - .sign(blinded_node_id_sign).unwrap(); + payment_paths(), + payment_hash(), + now(), + pubkey(46), + ) + .unwrap() + .build() + .unwrap() + .sign(blinded_node_id_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -2688,14 +3040,23 @@ mod tests { .amount_msats(1000) .path(paths[0].clone()) .path(paths[1].clone()) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() .respond_with_no_std_using_signing_pubkey( - payment_paths(), payment_hash(), now(), recipient_pubkey() - ).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + payment_paths(), + payment_hash(), + now(), + recipient_pubkey(), + ) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); @@ -2703,7 +3064,10 @@ mod tests { match Bolt12Invoice::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidSigningPubkey)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidSigningPubkey) + ); }, } } @@ -2718,56 +3082,85 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .amount_msats_unchecked(2000) - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); match Bolt12Invoice::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount) + ), } let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(1000).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(1000) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .amount_msats_unchecked(2000) - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); match Bolt12Invoice::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount) + ), } - let invoice = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap() + let invoice = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() + .build() + .unwrap() .respond_using_derived_keys_no_std( - payment_paths(), payment_hash(), now(), &expanded_key, &entropy + payment_paths(), + payment_hash(), + now(), + &expanded_key, + &entropy, ) .unwrap() .amount_msats_unchecked(2000) - .build_and_sign(&secp_ctx).unwrap(); + .build_and_sign(&secp_ctx) + .unwrap(); let mut buffer = Vec::new(); invoice.write(&mut buffer).unwrap(); match Bolt12Invoice::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount) + ), } } @@ -2782,17 +3175,26 @@ mod tests { let mut buffer = Vec::new(); OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() .contents - .write(&mut buffer).unwrap(); + .write(&mut buffer) + .unwrap(); match Bolt12Invoice::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature) + ), } } @@ -2806,12 +3208,18 @@ mod tests { let mut invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let last_signature_byte = invoice.bytes.last_mut().unwrap(); *last_signature_byte = last_signature_byte.wrapping_add(1); @@ -2821,7 +3229,10 @@ mod tests { match Bolt12Invoice::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSignature(secp256k1::Error::IncorrectSignature)); + assert_eq!( + e, + Bolt12ParseError::InvalidSignature(secp256k1::Error::IncorrectSignature) + ); }, } } @@ -2840,11 +3251,16 @@ mod tests { let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let mut unsigned_invoice = OfferBuilder::new(keys.public_key()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap(); let mut unknown_bytes = Vec::new(); BigSize(UNKNOWN_ODD_TYPE).write(&mut unknown_bytes).unwrap(); @@ -2856,9 +3272,9 @@ mod tests { TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &unsigned_invoice.bytes); let invoice = unsigned_invoice - .sign(|message: &UnsignedBolt12Invoice| + .sign(|message: &UnsignedBolt12Invoice| { Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) + }) .unwrap(); let mut encoded_invoice = Vec::new(); @@ -2874,11 +3290,16 @@ mod tests { let mut unsigned_invoice = OfferBuilder::new(keys.public_key()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap(); let mut unknown_bytes = Vec::new(); BigSize(UNKNOWN_EVEN_TYPE).write(&mut unknown_bytes).unwrap(); @@ -2890,9 +3311,9 @@ mod tests { TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &unsigned_invoice.bytes); let invoice = unsigned_invoice - .sign(|message: &UnsignedBolt12Invoice| + .sign(|message: &UnsignedBolt12Invoice| { Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) + }) .unwrap(); let mut encoded_invoice = Vec::new(); @@ -2915,15 +3336,20 @@ mod tests { let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let invoice = OfferBuilder::new(keys.public_key()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() .experimental_baz(42) - .build().unwrap() - .sign(|message: &UnsignedBolt12Invoice| + .build() + .unwrap() + .sign(|message: &UnsignedBolt12Invoice| { Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) + }) .unwrap(); let mut encoded_invoice = Vec::new(); @@ -2936,11 +3362,16 @@ mod tests { let mut unsigned_invoice = OfferBuilder::new(keys.public_key()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap(); let mut unknown_bytes = Vec::new(); BigSize(UNKNOWN_ODD_TYPE).write(&mut unknown_bytes).unwrap(); @@ -2954,9 +3385,9 @@ mod tests { unsigned_invoice.tagged_hash = TaggedHash::from_tlv_stream(SIGNATURE_TAG, tlv_stream); let invoice = unsigned_invoice - .sign(|message: &UnsignedBolt12Invoice| + .sign(|message: &UnsignedBolt12Invoice| { Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) + }) .unwrap(); let mut encoded_invoice = Vec::new(); @@ -2972,11 +3403,16 @@ mod tests { let mut unsigned_invoice = OfferBuilder::new(keys.public_key()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap(); let mut unknown_bytes = Vec::new(); BigSize(UNKNOWN_EVEN_TYPE).write(&mut unknown_bytes).unwrap(); @@ -2990,9 +3426,9 @@ mod tests { unsigned_invoice.tagged_hash = TaggedHash::from_tlv_stream(SIGNATURE_TAG, tlv_stream); let invoice = unsigned_invoice - .sign(|message: &UnsignedBolt12Invoice| + .sign(|message: &UnsignedBolt12Invoice| { Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) + }) .unwrap(); let mut encoded_invoice = Vec::new(); @@ -3005,14 +3441,19 @@ mod tests { let invoice = OfferBuilder::new(keys.public_key()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(|message: &UnsignedBolt12Invoice| + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(|message: &UnsignedBolt12Invoice| { Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) + }) .unwrap(); let mut encoded_invoice = Vec::new(); @@ -3024,7 +3465,10 @@ mod tests { match Bolt12Invoice::try_from(encoded_invoice) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSignature(secp256k1::Error::IncorrectSignature)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSignature(secp256k1::Error::IncorrectSignature) + ), } } @@ -3038,12 +3482,18 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let mut encoded_invoice = Vec::new(); invoice.write(&mut encoded_invoice).unwrap(); @@ -3067,19 +3517,26 @@ mod tests { let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap() + .respond_with_no_std(payment_paths(), payment_hash(), now()) + .unwrap() + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); let blinded_path = BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(42), encrypted_payload: vec![0; 43] }, BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 44] }, - ] + ], ); let mut tlv_stream = invoice.as_tlv_stream(); @@ -3088,7 +3545,10 @@ mod tests { match Bolt12Invoice::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedPaths)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedPaths) + ), } } } From d6f6024ce2c4f14ccb4efed79b6bac4392cd1b01 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:54:45 +0100 Subject: [PATCH 02/22] `rustfmt`: Drop `lightning/src/offers/invoice.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index 0883d9a23db..e05bb641ef0 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -38,7 +38,6 @@ lightning/src/ln/script.rs lightning/src/ln/shutdown_tests.rs lightning/src/ln/types.rs lightning/src/ln/wire.rs -lightning/src/offers/invoice.rs lightning/src/offers/invoice_error.rs lightning/src/offers/invoice_request.rs lightning/src/offers/merkle.rs From e1cab931c3760055b8de25e1acc1fad4076863ba Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:54:50 +0100 Subject: [PATCH 03/22] `rustfmt`: Run on `lightning/src/offers/invoice_error.rs` --- lightning/src/offers/invoice_error.rs | 30 +++++++++------------------ 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/lightning/src/offers/invoice_error.rs b/lightning/src/offers/invoice_error.rs index 5ae5f457a84..d8da795ccca 100644 --- a/lightning/src/offers/invoice_error.rs +++ b/lightning/src/offers/invoice_error.rs @@ -53,10 +53,7 @@ pub struct ErroneousField { impl InvoiceError { /// Creates an [`InvoiceError`] with the given message. pub fn from_string(s: String) -> Self { - Self { - erroneous_field: None, - message: UntrustedString(s), - } + Self { erroneous_field: None, message: UntrustedString(s) } } } @@ -107,10 +104,7 @@ impl Readable for InvoiceError { impl From for InvoiceError { fn from(error: Bolt12SemanticError) -> Self { - InvoiceError { - erroneous_field: None, - message: UntrustedString(format!("{:?}", error)), - } + InvoiceError { erroneous_field: None, message: UntrustedString(format!("{:?}", error)) } } } @@ -120,10 +114,7 @@ impl From for InvoiceError { SignError::Signing => "Failed signing invoice", SignError::Verification(_) => "Failed invoice signature verification", }; - InvoiceError { - erroneous_field: None, - message: UntrustedString(message.to_string()), - } + InvoiceError { erroneous_field: None, message: UntrustedString(message.to_string()) } } } @@ -132,7 +123,9 @@ mod tests { use super::{ErroneousField, InvoiceError}; use crate::ln::msgs::DecodeError; - use crate::util::ser::{HighZeroBytesDroppedBigSize, Readable, VecWriter, WithoutLength, Writeable}; + use crate::util::ser::{ + HighZeroBytesDroppedBigSize, Readable, VecWriter, WithoutLength, Writeable, + }; use crate::util::string::UntrustedString; #[test] @@ -149,7 +142,7 @@ mod tests { Ok(invoice_error) => { assert_eq!(invoice_error.message, UntrustedString("Invalid value".to_string())); assert_eq!(invoice_error.erroneous_field, None); - } + }, Err(e) => panic!("Unexpected error: {:?}", e), } } @@ -174,7 +167,7 @@ mod tests { invoice_error.erroneous_field, Some(ErroneousField { tlv_fieldnum: 42, suggested_value: Some(vec![42; 32]) }), ); - } + }, Err(e) => panic!("Unexpected error: {:?}", e), } } @@ -183,10 +176,7 @@ mod tests { fn parses_invoice_error_without_suggested_value() { let mut writer = VecWriter(Vec::new()); let invoice_error = InvoiceError { - erroneous_field: Some(ErroneousField { - tlv_fieldnum: 42, - suggested_value: None, - }), + erroneous_field: Some(ErroneousField { tlv_fieldnum: 42, suggested_value: None }), message: UntrustedString("Invalid value".to_string()), }; invoice_error.write(&mut writer).unwrap(); @@ -199,7 +189,7 @@ mod tests { invoice_error.erroneous_field, Some(ErroneousField { tlv_fieldnum: 42, suggested_value: None }), ); - } + }, Err(e) => panic!("Unexpected error: {:?}", e), } } From 63eda068642a56b1826bd4c7ced8a60de169a032 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:54:51 +0100 Subject: [PATCH 04/22] `rustfmt`: Drop `lightning/src/offers/invoice_error.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index e05bb641ef0..b17f38f7dfb 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -38,7 +38,6 @@ lightning/src/ln/script.rs lightning/src/ln/shutdown_tests.rs lightning/src/ln/types.rs lightning/src/ln/wire.rs -lightning/src/offers/invoice_error.rs lightning/src/offers/invoice_request.rs lightning/src/offers/merkle.rs lightning/src/offers/mod.rs From 9fc9b88c7f4e834a8dfe9daf398520dfa063b368 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Mon, 10 Feb 2025 11:01:09 +0100 Subject: [PATCH 05/22] `rustfmt`: Prepare `lightning/src/offers/invoice_request.rs` --- lightning/src/offers/invoice_request.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lightning/src/offers/invoice_request.rs b/lightning/src/offers/invoice_request.rs index 8d7d25cf2b5..5ed28ffcce5 100644 --- a/lightning/src/offers/invoice_request.rs +++ b/lightning/src/offers/invoice_request.rs @@ -771,6 +771,7 @@ macro_rules! invoice_request_verify_method { ($self: ident, $self_type: ty) => { /// [`Bolt12Invoice`] for the request if they could be extracted from the metadata. /// /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice + #[rustfmt::skip] pub fn verify_using_metadata< #[cfg(not(c_bindings))] T: secp256k1::Signing @@ -800,6 +801,7 @@ macro_rules! invoice_request_verify_method { ($self: ident, $self_type: ty) => { /// [`Bolt12Invoice`] for the request if they could be extracted from the metadata. /// /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice + #[rustfmt::skip] pub fn verify_using_recipient_data< #[cfg(not(c_bindings))] T: secp256k1::Signing From 20cb35fdee3a0bcdefc62b2700529029692d9d40 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:04 +0100 Subject: [PATCH 06/22] `rustfmt`: Run on `lightning/src/offers/invoice_request.rs` --- lightning/src/offers/invoice_request.rs | 1075 +++++++++++++++-------- 1 file changed, 702 insertions(+), 373 deletions(-) diff --git a/lightning/src/offers/invoice_request.rs b/lightning/src/offers/invoice_request.rs index 5ed28ffcce5..a374a055e70 100644 --- a/lightning/src/offers/invoice_request.rs +++ b/lightning/src/offers/invoice_request.rs @@ -65,35 +65,40 @@ //! # } //! ``` -use bitcoin::constants::ChainHash; -use bitcoin::network::Network; -use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, self}; -use bitcoin::secp256k1::schnorr::Signature; -use crate::io; use crate::blinded_path::message::BlindedMessagePath; use crate::blinded_path::payment::BlindedPaymentPath; -use crate::types::payment::PaymentHash; +use crate::io; use crate::ln::channelmanager::PaymentId; -use crate::types::features::InvoiceRequestFeatures; use crate::ln::inbound_payment::{ExpandedKey, IV_LEN}; use crate::ln::msgs::DecodeError; -use crate::offers::merkle::{SignError, SignFn, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, TlvStream, self}; +use crate::offers::merkle::{ + self, SignError, SignFn, SignatureTlvStream, SignatureTlvStreamRef, TaggedHash, TlvStream, +}; use crate::offers::nonce::Nonce; -use crate::offers::offer::{Amount, EXPERIMENTAL_OFFER_TYPES, ExperimentalOfferTlvStream, ExperimentalOfferTlvStreamRef, OFFER_TYPES, Offer, OfferContents, OfferId, OfferTlvStream, OfferTlvStreamRef}; -use crate::offers::parse::{Bolt12ParseError, ParsedMessage, Bolt12SemanticError}; +use crate::offers::offer::{ + Amount, ExperimentalOfferTlvStream, ExperimentalOfferTlvStreamRef, Offer, OfferContents, + OfferId, OfferTlvStream, OfferTlvStreamRef, EXPERIMENTAL_OFFER_TYPES, OFFER_TYPES, +}; +use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError, ParsedMessage}; use crate::offers::payer::{PayerContents, PayerTlvStream, PayerTlvStreamRef}; use crate::offers::signer::{Metadata, MetadataMaterial}; use crate::onion_message::dns_resolution::HumanReadableName; -use crate::util::ser::{CursorReadable, HighZeroBytesDroppedBigSize, Readable, WithoutLength, Writeable, Writer}; +use crate::types::features::InvoiceRequestFeatures; +use crate::types::payment::PaymentHash; +use crate::util::ser::{ + CursorReadable, HighZeroBytesDroppedBigSize, Readable, WithoutLength, Writeable, Writer, +}; use crate::util::string::{PrintableString, UntrustedString}; +use bitcoin::constants::ChainHash; +use bitcoin::network::Network; +use bitcoin::secp256k1::schnorr::Signature; +use bitcoin::secp256k1::{self, Keypair, PublicKey, Secp256k1}; #[cfg(not(c_bindings))] -use { - crate::offers::invoice::{DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder}, -}; +use crate::offers::invoice::{DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder}; #[cfg(c_bindings)] -use { - crate::offers::invoice::{InvoiceWithDerivedSigningPubkeyBuilder, InvoiceWithExplicitSigningPubkeyBuilder}, +use crate::offers::invoice::{ + InvoiceWithDerivedSigningPubkeyBuilder, InvoiceWithExplicitSigningPubkeyBuilder, }; #[allow(unused_imports)] @@ -131,42 +136,44 @@ pub struct InvoiceRequestWithDerivedPayerSigningPubkeyBuilder<'a, 'b> { secp_ctx: Option<&'b Secp256k1>, } -macro_rules! invoice_request_derived_payer_signing_pubkey_builder_methods { ( +macro_rules! invoice_request_derived_payer_signing_pubkey_builder_methods { + ( $self: ident, $self_type: ty, $secp_context: ty ) => { - #[cfg_attr(c_bindings, allow(dead_code))] - pub(super) fn deriving_signing_pubkey( - offer: &'a Offer, expanded_key: &ExpandedKey, nonce: Nonce, - secp_ctx: &'b Secp256k1<$secp_context>, payment_id: PaymentId - ) -> Self { - let payment_id = Some(payment_id); - let derivation_material = MetadataMaterial::new(nonce, expanded_key, payment_id); - let metadata = Metadata::DerivedSigningPubkey(derivation_material); - Self { - offer, - invoice_request: Self::create_contents(offer, metadata), - payer_signing_pubkey: None, - secp_ctx: Some(secp_ctx), + #[cfg_attr(c_bindings, allow(dead_code))] + pub(super) fn deriving_signing_pubkey( + offer: &'a Offer, expanded_key: &ExpandedKey, nonce: Nonce, + secp_ctx: &'b Secp256k1<$secp_context>, payment_id: PaymentId, + ) -> Self { + let payment_id = Some(payment_id); + let derivation_material = MetadataMaterial::new(nonce, expanded_key, payment_id); + let metadata = Metadata::DerivedSigningPubkey(derivation_material); + Self { + offer, + invoice_request: Self::create_contents(offer, metadata), + payer_signing_pubkey: None, + secp_ctx: Some(secp_ctx), + } } - } - - /// Builds a signed [`InvoiceRequest`] after checking for valid semantics. - pub fn build_and_sign($self: $self_type) -> Result { - 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(|message: &UnsignedInvoiceRequest| - Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) - .unwrap(); - Ok(invoice_request) - } -} } + /// Builds a signed [`InvoiceRequest`] after checking for valid semantics. + pub fn build_and_sign($self: $self_type) -> Result { + 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(|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, $secp_context: ty $(, $self_mut: tt)? @@ -414,15 +421,17 @@ impl<'a, 'b> InvoiceRequestWithDerivedPayerSigningPubkeyBuilder<'a, 'b> { #[cfg(c_bindings)] impl<'a, 'b> From> -for InvoiceRequestBuilder<'a, 'b, secp256k1::All> { + for InvoiceRequestBuilder<'a, 'b, secp256k1::All> +{ fn from(builder: InvoiceRequestWithDerivedPayerSigningPubkeyBuilder<'a, 'b>) -> Self { let InvoiceRequestWithDerivedPayerSigningPubkeyBuilder { - offer, invoice_request, payer_signing_pubkey, secp_ctx, + offer, + invoice_request, + payer_signing_pubkey, + secp_ctx, } = builder; - Self { - offer, invoice_request, payer_signing_pubkey, secp_ctx, - } + Self { offer, invoice_request, payer_signing_pubkey, secp_ctx } } } @@ -469,8 +478,11 @@ impl UnsignedInvoiceRequest { // Use the offer bytes instead of the offer TLV stream as the offer may have contained // unknown TLV records, which are not stored in `OfferContents`. let ( - payer_tlv_stream, _offer_tlv_stream, invoice_request_tlv_stream, - _experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, + payer_tlv_stream, + _offer_tlv_stream, + invoice_request_tlv_stream, + _experimental_offer_tlv_stream, + experimental_invoice_request_tlv_stream, ) = contents.as_tlv_stream(); const INVOICE_REQUEST_ALLOCATION_SIZE: usize = 512; @@ -489,8 +501,8 @@ impl UnsignedInvoiceRequest { const EXPERIMENTAL_TLV_ALLOCATION_SIZE: usize = 0; let mut experimental_bytes = Vec::with_capacity(EXPERIMENTAL_TLV_ALLOCATION_SIZE); - let experimental_tlv_stream = TlvStream::new(remaining_bytes) - .range(EXPERIMENTAL_OFFER_TYPES); + let experimental_tlv_stream = + TlvStream::new(remaining_bytes).range(EXPERIMENTAL_OFFER_TYPES); for record in experimental_tlv_stream { record.write(&mut experimental_bytes).unwrap(); } @@ -588,10 +600,16 @@ pub struct VerifiedInvoiceRequest { /// Keys used for signing a [`Bolt12Invoice`] if they can be derived. /// - #[cfg_attr(feature = "std", doc = "If `Some`, must call [`respond_using_derived_keys`] when responding. Otherwise, call [`respond_with`].")] + #[cfg_attr( + feature = "std", + doc = "If `Some`, must call [`respond_using_derived_keys`] when responding. Otherwise, call [`respond_with`]." + )] #[cfg_attr(feature = "std", doc = "")] /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice - #[cfg_attr(feature = "std", doc = "[`respond_using_derived_keys`]: Self::respond_using_derived_keys")] + #[cfg_attr( + feature = "std", + doc = "[`respond_using_derived_keys`]: Self::respond_using_derived_keys" + )] #[cfg_attr(feature = "std", doc = "[`respond_with`]: Self::respond_with")] pub keys: Option, } @@ -763,8 +781,9 @@ macro_rules! invoice_request_respond_with_explicit_signing_pubkey_methods { ( } } } -macro_rules! invoice_request_verify_method { ($self: ident, $self_type: ty) => { - /// Verifies that the request was for an offer created using the given key by checking the +macro_rules! invoice_request_verify_method { + ($self: ident, $self_type: ty) => { +/// Verifies that the request was for an offer created using the given key by checking the /// metadata from the offer. /// /// Returns the verified request which contains the derived keys needed to sign a @@ -794,7 +813,7 @@ macro_rules! invoice_request_verify_method { ($self: ident, $self_type: ty) => { }) } - /// Verifies that the request was for an offer created using the given key by checking a nonce +/// Verifies that the request was for an offer created using the given key by checking a nonce /// included with the [`BlindedMessagePath`] for which the request was sent through. /// /// Returns the verified request which contains the derived keys needed to sign a @@ -824,13 +843,18 @@ macro_rules! invoice_request_verify_method { ($self: ident, $self_type: ty) => { 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); + invoice_request_respond_with_explicit_signing_pubkey_methods!( + self, + self, + InvoiceBuilder + ); invoice_request_verify_method!(self, Self); #[cfg(async_payments)] @@ -843,7 +867,11 @@ impl InvoiceRequest { 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_respond_with_explicit_signing_pubkey_methods!( + self, + self, + InvoiceWithExplicitSigningPubkeyBuilder + ); invoice_request_verify_method!(self, &Self); } @@ -857,15 +885,19 @@ impl InvoiceRequest { pub(crate) fn as_tlv_stream(&self) -> FullInvoiceRequestTlvStreamRef { let ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, - experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + experimental_offer_tlv_stream, + experimental_invoice_request_tlv_stream, ) = self.contents.as_tlv_stream(); - let signature_tlv_stream = SignatureTlvStreamRef { - signature: Some(&self.signature), - }; + let signature_tlv_stream = SignatureTlvStreamRef { signature: Some(&self.signature) }; ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, - signature_tlv_stream, experimental_offer_tlv_stream, + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + signature_tlv_stream, + experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, ) } @@ -927,27 +959,43 @@ 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); + invoice_request_respond_with_explicit_signing_pubkey_methods!( + self, + self.inner, + InvoiceBuilder + ); #[cfg(c_bindings)] - invoice_request_respond_with_explicit_signing_pubkey_methods!(self, self.inner, InvoiceWithExplicitSigningPubkeyBuilder); + 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); + invoice_request_respond_with_derived_signing_pubkey_methods!( + self, + self.inner, + InvoiceBuilder + ); #[cfg(c_bindings)] - invoice_request_respond_with_derived_signing_pubkey_methods!(self, self.inner, InvoiceWithDerivedSigningPubkeyBuilder); + invoice_request_respond_with_derived_signing_pubkey_methods!( + self, + self.inner, + InvoiceWithDerivedSigningPubkeyBuilder + ); pub(crate) fn fields(&self) -> InvoiceRequestFields { let InvoiceRequestContents { payer_signing_pubkey, - inner: InvoiceRequestContentsWithoutPayerSigningPubkey { - quantity, payer_note, .. - }, + inner: InvoiceRequestContentsWithoutPayerSigningPubkey { quantity, payer_note, .. }, } = &self.inner.contents; InvoiceRequestFields { payer_signing_pubkey: *payer_signing_pubkey, quantity: *quantity, - payer_note_truncated: payer_note.clone() - .map(|mut s| { s.truncate(PAYER_NOTE_LIMIT); UntrustedString(s) }), + payer_note_truncated: payer_note.clone().map(|mut s| { + s.truncate(PAYER_NOTE_LIMIT); + UntrustedString(s) + }), human_readable_name: self.offer_from_hrn().clone(), } } @@ -963,15 +1011,16 @@ impl InvoiceRequestContents { } pub(super) fn amount_msats(&self) -> Option { - self.inner - .amount_msats() - .or_else(|| match self.inner.offer.amount() { - Some(Amount::Bitcoin { amount_msats }) => { - Some(amount_msats.saturating_mul(self.quantity().unwrap_or(1))) - }, - Some(Amount::Currency { .. }) => None, - None => { debug_assert!(false); None}, - }) + self.inner.amount_msats().or_else(|| match self.inner.offer.amount() { + Some(Amount::Bitcoin { amount_msats }) => { + Some(amount_msats.saturating_mul(self.quantity().unwrap_or(1))) + }, + Some(Amount::Currency { .. }) => None, + None => { + debug_assert!(false); + None + }, + }) } pub(super) fn has_amount_msats(&self) -> bool { @@ -991,8 +1040,7 @@ impl InvoiceRequestContents { } pub(super) fn payer_note(&self) -> Option { - self.inner.payer_note.as_ref() - .map(|payer_note| PrintableString(payer_note.as_str())) + self.inner.payer_note.as_ref().map(|payer_note| PrintableString(payer_note.as_str())) } pub(super) fn offer_from_hrn(&self) -> &Option { @@ -1021,15 +1069,16 @@ impl InvoiceRequestContentsWithoutPayerSigningPubkey { } pub(super) fn as_tlv_stream(&self) -> PartialInvoiceRequestTlvStreamRef { - let payer = PayerTlvStreamRef { - metadata: self.payer.0.as_bytes(), - }; + let payer = PayerTlvStreamRef { metadata: self.payer.0.as_bytes() }; let (offer, experimental_offer) = self.offer.as_tlv_stream(); let features = { - if self.features == InvoiceRequestFeatures::empty() { None } - else { Some(&self.features) } + if self.features == InvoiceRequestFeatures::empty() { + None + } else { + Some(&self.features) + } }; let invoice_request = InvoiceRequestTlvStreamRef { @@ -1106,8 +1155,10 @@ pub(super) const EXPERIMENTAL_INVOICE_REQUEST_TYPES: core::ops::Range = #[cfg(not(test))] tlv_stream!( - ExperimentalInvoiceRequestTlvStream, ExperimentalInvoiceRequestTlvStreamRef, - EXPERIMENTAL_INVOICE_REQUEST_TYPES, { + ExperimentalInvoiceRequestTlvStream, + ExperimentalInvoiceRequestTlvStreamRef, + EXPERIMENTAL_INVOICE_REQUEST_TYPES, + { // When adding experimental TLVs, update EXPERIMENTAL_TLV_ALLOCATION_SIZE accordingly in // UnsignedInvoiceRequest::new to avoid unnecessary allocations. } @@ -1122,8 +1173,12 @@ tlv_stream!( ); type FullInvoiceRequestTlvStream = ( - PayerTlvStream, OfferTlvStream, InvoiceRequestTlvStream, SignatureTlvStream, - ExperimentalOfferTlvStream, ExperimentalInvoiceRequestTlvStream, + PayerTlvStream, + OfferTlvStream, + InvoiceRequestTlvStream, + SignatureTlvStream, + ExperimentalOfferTlvStream, + ExperimentalInvoiceRequestTlvStream, ); type FullInvoiceRequestTlvStreamRef<'a> = ( @@ -1144,17 +1199,22 @@ impl CursorReadable for FullInvoiceRequestTlvStream { let experimental_offer = CursorReadable::read(r)?; let experimental_invoice_request = CursorReadable::read(r)?; - Ok( - ( - payer, offer, invoice_request, signature, experimental_offer, - experimental_invoice_request, - ) - ) + Ok(( + payer, + offer, + invoice_request, + signature, + experimental_offer, + experimental_invoice_request, + )) } } type PartialInvoiceRequestTlvStream = ( - PayerTlvStream, OfferTlvStream, InvoiceRequestTlvStream, ExperimentalOfferTlvStream, + PayerTlvStream, + OfferTlvStream, + InvoiceRequestTlvStream, + ExperimentalOfferTlvStream, ExperimentalInvoiceRequestTlvStream, ); @@ -1193,20 +1253,27 @@ impl TryFrom> for InvoiceRequest { let invoice_request = ParsedMessage::::try_from(bytes)?; let ParsedMessage { bytes, tlv_stream } = invoice_request; let ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, SignatureTlvStream { signature }, experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, ) = tlv_stream; - let contents = InvoiceRequestContents::try_from( - ( - payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, - experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, - ) - )?; + let contents = InvoiceRequestContents::try_from(( + payer_tlv_stream, + offer_tlv_stream, + invoice_request_tlv_stream, + experimental_offer_tlv_stream, + experimental_invoice_request_tlv_stream, + ))?; let signature = match signature { - None => return Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature)), + None => { + return Err(Bolt12ParseError::InvalidSemantics( + Bolt12SemanticError::MissingSignature, + )) + }, Some(signature) => signature, }; let message = TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &bytes); @@ -1224,7 +1291,13 @@ impl TryFrom for InvoiceRequestContents { PayerTlvStream { metadata }, offer_tlv_stream, InvoiceRequestTlvStream { - chain, amount, features, quantity, payer_id, payer_note, paths, + chain, + amount, + features, + quantity, + payer_id, + payer_note, + paths, offer_from_hrn, }, experimental_offer_tlv_stream, @@ -1264,7 +1337,13 @@ impl TryFrom for InvoiceRequestContents { Ok(InvoiceRequestContents { inner: InvoiceRequestContentsWithoutPayerSigningPubkey { - payer, offer, chain, amount_msats: amount, features, quantity, payer_note, + payer, + offer, + chain, + amount_msats: amount, + features, + quantity, + payer_note, offer_from_hrn, #[cfg(test)] experimental_bar, @@ -1328,35 +1407,37 @@ impl Readable for InvoiceRequestFields { #[cfg(test)] mod tests { - use super::{EXPERIMENTAL_INVOICE_REQUEST_TYPES, ExperimentalInvoiceRequestTlvStreamRef, INVOICE_REQUEST_TYPES, InvoiceRequest, InvoiceRequestFields, InvoiceRequestTlvStreamRef, PAYER_NOTE_LIMIT, SIGNATURE_TAG, UnsignedInvoiceRequest}; + use super::{ + ExperimentalInvoiceRequestTlvStreamRef, InvoiceRequest, InvoiceRequestFields, + InvoiceRequestTlvStreamRef, UnsignedInvoiceRequest, EXPERIMENTAL_INVOICE_REQUEST_TYPES, + INVOICE_REQUEST_TYPES, PAYER_NOTE_LIMIT, SIGNATURE_TAG, + }; - use bitcoin::constants::ChainHash; - use bitcoin::network::Network; - use bitcoin::secp256k1::{Keypair, Secp256k1, SecretKey, self}; - use core::num::NonZeroU64; - #[cfg(feature = "std")] - use core::time::Duration; use crate::ln::channelmanager::PaymentId; - use crate::types::features::{InvoiceRequestFeatures, OfferFeatures}; use crate::ln::inbound_payment::ExpandedKey; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; use crate::offers::invoice::{Bolt12Invoice, SIGNATURE_TAG as INVOICE_SIGNATURE_TAG}; - use crate::offers::merkle::{SignatureTlvStreamRef, TaggedHash, TlvStream, self}; + use crate::offers::merkle::{self, SignatureTlvStreamRef, TaggedHash, TlvStream}; use crate::offers::nonce::Nonce; - use crate::offers::offer::{Amount, ExperimentalOfferTlvStreamRef, OfferTlvStreamRef, Quantity}; #[cfg(not(c_bindings))] - use { - crate::offers::offer::OfferBuilder, - }; + use crate::offers::offer::OfferBuilder; #[cfg(c_bindings)] - use { - crate::offers::offer::OfferWithExplicitMetadataBuilder as OfferBuilder, + use crate::offers::offer::OfferWithExplicitMetadataBuilder as OfferBuilder; + use crate::offers::offer::{ + Amount, ExperimentalOfferTlvStreamRef, OfferTlvStreamRef, Quantity, }; use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError}; use crate::offers::payer::PayerTlvStreamRef; use crate::offers::test_utils::*; + use crate::types::features::{InvoiceRequestFeatures, OfferFeatures}; use crate::util::ser::{BigSize, Readable, Writeable}; use crate::util::string::{PrintableString, UntrustedString}; + use bitcoin::constants::ChainHash; + use bitcoin::network::Network; + use bitcoin::secp256k1::{self, Keypair, Secp256k1, SecretKey}; + use core::num::NonZeroU64; + #[cfg(feature = "std")] + use core::time::Duration; #[test] fn builds_invoice_request_with_defaults() { @@ -1369,16 +1450,22 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); assert_eq!(invoice_request.bytes, buffer.as_slice()); assert_eq!(invoice_request.payer_metadata(), &encrypted_payment_id); - assert_eq!(invoice_request.chains(), vec![ChainHash::using_genesis_block(Network::Bitcoin)]); + assert_eq!( + invoice_request.chains(), + vec![ChainHash::using_genesis_block(Network::Bitcoin)] + ); assert_eq!(invoice_request.metadata(), None); assert_eq!(invoice_request.amount(), Some(Amount::Bitcoin { amount_msats: 1000 })); assert_eq!(invoice_request.description(), Some(PrintableString(""))); @@ -1394,12 +1481,14 @@ mod tests { assert_eq!(invoice_request.quantity(), None); assert_eq!(invoice_request.payer_note(), None); - let message = TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &invoice_request.bytes); - assert!( - merkle::verify_signature( - &invoice_request.signature, &message, invoice_request.payer_signing_pubkey(), - ).is_ok() - ); + let message = + TaggedHash::from_valid_tlv_stream_bytes(SIGNATURE_TAG, &invoice_request.bytes); + assert!(merkle::verify_signature( + &invoice_request.signature, + &message, + invoice_request.payer_signing_pubkey(), + ) + .is_ok()); assert_eq!( invoice_request.as_tlv_stream(), @@ -1429,12 +1518,8 @@ mod tests { offer_from_hrn: None, }, SignatureTlvStreamRef { signature: Some(&invoice_request.signature()) }, - ExperimentalOfferTlvStreamRef { - experimental_foo: None, - }, - ExperimentalInvoiceRequestTlvStreamRef { - experimental_bar: None, - }, + ExperimentalOfferTlvStreamRef { experimental_foo: None }, + ExperimentalInvoiceRequestTlvStreamRef { experimental_bar: None }, ), ); @@ -1458,8 +1543,10 @@ mod tests { if let Err(e) = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .absolute_expiry(future_expiry) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_and_sign() { panic!("error building invoice_request: {:?}", e); @@ -1468,8 +1555,10 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .absolute_expiry(past_expiry) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_and_sign() { Ok(_) => panic!("expected error"), @@ -1488,28 +1577,38 @@ mod tests { let offer = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .experimental_foo(42) - .build().unwrap(); + .build() + .unwrap(); let invoice_request = offer - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .experimental_bar(42) .build_and_sign() .unwrap(); - let invoice = invoice_request.respond_with_no_std(payment_paths(), payment_hash(), now()) + let invoice = invoice_request + .respond_with_no_std(payment_paths(), payment_hash(), now()) .unwrap() .experimental_baz(42) - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); assert!(invoice.verify_using_metadata(&expanded_key, &secp_ctx).is_err()); - assert!( - invoice.verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx).is_ok() - ); + assert!(invoice + .verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx) + .is_ok()); // Fails verification with altered fields let ( - payer_tlv_stream, offer_tlv_stream, mut invoice_request_tlv_stream, - mut invoice_tlv_stream, mut signature_tlv_stream, experimental_offer_tlv_stream, - experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream, + payer_tlv_stream, + offer_tlv_stream, + mut invoice_request_tlv_stream, + mut invoice_tlv_stream, + mut signature_tlv_stream, + experimental_offer_tlv_stream, + experimental_invoice_request_tlv_stream, + experimental_invoice_tlv_stream, ) = invoice.as_tlv_stream(); invoice_request_tlv_stream.amount = Some(2000); invoice_tlv_stream.amount = Some(2000); @@ -1517,7 +1616,8 @@ mod tests { let tlv_stream = (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream); let experimental_tlv_stream = ( - experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, + experimental_offer_tlv_stream, + experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream, ); let mut bytes = Vec::new(); @@ -1533,15 +1633,20 @@ mod tests { .unwrap(); let invoice = Bolt12Invoice::try_from(encoded_invoice).unwrap(); - assert!( - invoice.verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx).is_err() - ); + assert!(invoice + .verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx) + .is_err()); // Fails verification with altered payer id let ( - payer_tlv_stream, offer_tlv_stream, mut invoice_request_tlv_stream, invoice_tlv_stream, - mut signature_tlv_stream, experimental_offer_tlv_stream, - experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream, + payer_tlv_stream, + offer_tlv_stream, + mut invoice_request_tlv_stream, + invoice_tlv_stream, + mut signature_tlv_stream, + experimental_offer_tlv_stream, + experimental_invoice_request_tlv_stream, + experimental_invoice_tlv_stream, ) = invoice.as_tlv_stream(); let payer_id = pubkey(1); invoice_request_tlv_stream.payer_id = Some(&payer_id); @@ -1549,7 +1654,8 @@ mod tests { let tlv_stream = (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream); let experimental_tlv_stream = ( - experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream, + experimental_offer_tlv_stream, + experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream, ); let mut bytes = Vec::new(); @@ -1565,9 +1671,9 @@ mod tests { .unwrap(); let invoice = Bolt12Invoice::try_from(encoded_invoice).unwrap(); - assert!( - invoice.verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx).is_err() - ); + assert!(invoice + .verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx) + .is_err()); } #[test] @@ -1583,10 +1689,14 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .chain(Network::Bitcoin).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .chain(Network::Bitcoin) + .unwrap() + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.chain(), mainnet); assert_eq!(tlv_stream.chain, None); @@ -1594,10 +1704,14 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .chain(Network::Testnet) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .chain(Network::Testnet).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .chain(Network::Testnet) + .unwrap() + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.chain(), testnet); assert_eq!(tlv_stream.chain, Some(&testnet)); @@ -1606,10 +1720,14 @@ mod tests { .amount_msats(1000) .chain(Network::Bitcoin) .chain(Network::Testnet) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .chain(Network::Bitcoin).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .chain(Network::Bitcoin) + .unwrap() + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.chain(), mainnet); assert_eq!(tlv_stream.chain, None); @@ -1618,11 +1736,16 @@ mod tests { .amount_msats(1000) .chain(Network::Bitcoin) .chain(Network::Testnet) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .chain(Network::Bitcoin).unwrap() - .chain(Network::Testnet).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .chain(Network::Bitcoin) + .unwrap() + .chain(Network::Testnet) + .unwrap() + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.chain(), testnet); assert_eq!(tlv_stream.chain, Some(&testnet)); @@ -1630,8 +1753,10 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .chain(Network::Testnet) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .chain(Network::Bitcoin) { Ok(_) => panic!("expected error"), @@ -1641,8 +1766,10 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .chain(Network::Testnet) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_and_sign() { Ok(_) => panic!("expected error"), @@ -1660,10 +1787,14 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(1000).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(1000) + .unwrap() + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert!(invoice_request.has_amount_msats()); assert_eq!(invoice_request.amount_msats(), Some(1000)); @@ -1671,11 +1802,16 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(1001).unwrap() - .amount_msats(1000).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(1001) + .unwrap() + .amount_msats(1000) + .unwrap() + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert!(invoice_request.has_amount_msats()); assert_eq!(invoice_request.amount_msats(), Some(1000)); @@ -1683,10 +1819,14 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(1001).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(1001) + .unwrap() + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert!(invoice_request.has_amount_msats()); assert_eq!(invoice_request.amount_msats(), Some(1001)); @@ -1694,8 +1834,10 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .amount_msats(999) { Ok(_) => panic!("expected error"), @@ -1705,9 +1847,12 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .quantity(2).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .quantity(2) + .unwrap() .amount_msats(1000) { Ok(_) => panic!("expected error"), @@ -1716,8 +1861,10 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .amount_msats(MAX_VALUE_MSAT + 1) { Ok(_) => panic!("expected error"), @@ -1727,10 +1874,14 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(1000).unwrap() - .quantity(2).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(1000) + .unwrap() + .quantity(2) + .unwrap() .build_and_sign() { Ok(_) => panic!("expected error"), @@ -1738,8 +1889,10 @@ mod tests { } match OfferBuilder::new(recipient_pubkey()) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_and_sign() { Ok(_) => panic!("expected error"), @@ -1749,9 +1902,12 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .quantity(u64::max_value()).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .quantity(u64::max_value()) + .unwrap() .build_and_sign() { Ok(_) => panic!("expected error"), @@ -1769,9 +1925,12 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert!(!invoice_request.has_amount_msats()); assert_eq!(invoice_request.amount_msats(), Some(1000)); @@ -1780,10 +1939,14 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .quantity(2).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .quantity(2) + .unwrap() + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert!(!invoice_request.has_amount_msats()); assert_eq!(invoice_request.amount_msats(), Some(2000)); @@ -1792,7 +1955,8 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount(Amount::Currency { iso4217_code: *b"USD", amount: 10 }) .build_unchecked() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_unchecked_and_sign(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert!(!invoice_request.has_amount_msats()); @@ -1810,21 +1974,27 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .features_unchecked(InvoiceRequestFeatures::unknown()) - .build_and_sign().unwrap(); + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.invoice_request_features(), &InvoiceRequestFeatures::unknown()); assert_eq!(tlv_stream.features, Some(&InvoiceRequestFeatures::unknown())); let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .features_unchecked(InvoiceRequestFeatures::unknown()) .features_unchecked(InvoiceRequestFeatures::empty()) - .build_and_sign().unwrap(); + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.invoice_request_features(), &InvoiceRequestFeatures::empty()); assert_eq!(tlv_stream.features, None); @@ -1844,9 +2014,12 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::One) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.quantity(), None); assert_eq!(tlv_stream.quantity, None); @@ -1854,9 +2027,12 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::One) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(2_000).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(2_000) + .unwrap() .quantity(2) { Ok(_) => panic!("expected error"), @@ -1866,11 +2042,16 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Bounded(ten)) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(10_000).unwrap() - .quantity(10).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(10_000) + .unwrap() + .quantity(10) + .unwrap() + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.amount_msats(), Some(10_000)); assert_eq!(tlv_stream.amount, Some(10_000)); @@ -1878,9 +2059,12 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Bounded(ten)) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(11_000).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(11_000) + .unwrap() .quantity(11) { Ok(_) => panic!("expected error"), @@ -1890,11 +2074,16 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(2_000).unwrap() - .quantity(2).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(2_000) + .unwrap() + .quantity(2) + .unwrap() + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.amount_msats(), Some(2_000)); assert_eq!(tlv_stream.amount, Some(2_000)); @@ -1902,8 +2091,10 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_and_sign() { Ok(_) => panic!("expected error"), @@ -1913,8 +2104,10 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Bounded(one)) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_and_sign() { Ok(_) => panic!("expected error"), @@ -1932,21 +2125,27 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .payer_note("bar".into()) - .build_and_sign().unwrap(); + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.payer_note(), Some(PrintableString("bar"))); assert_eq!(tlv_stream.payer_note, Some(&String::from("bar"))); let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .payer_note("bar".into()) .payer_note("baz".into()) - .build_and_sign().unwrap(); + .build_and_sign() + .unwrap(); let (_, _, tlv_stream, _, _, _) = invoice_request.as_tlv_stream(); assert_eq!(invoice_request.payer_note(), Some(PrintableString("baz"))); assert_eq!(tlv_stream.payer_note, Some(&String::from("baz"))); @@ -1962,10 +2161,13 @@ mod tests { match OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .features_unchecked(InvoiceRequestFeatures::unknown()) - .build_and_sign().unwrap() + .build_and_sign() + .unwrap() .respond_with_no_std(payment_paths(), payment_hash(), now()) { Ok(_) => panic!("expected error"), @@ -1983,9 +2185,12 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -2005,10 +2210,14 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .chain(Network::Bitcoin).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .chain(Network::Bitcoin) + .unwrap() + .build_and_sign() + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -2019,8 +2228,10 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .chain_unchecked(Network::Testnet) .build_unchecked_and_sign(); @@ -2029,7 +2240,10 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnsupportedChain)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnsupportedChain) + ), } } @@ -2043,9 +2257,12 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -2055,10 +2272,14 @@ mod tests { } let invoice_request = OfferBuilder::new(recipient_pubkey()) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(1000).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(1000) + .unwrap() + .build_and_sign() + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -2068,8 +2289,10 @@ mod tests { } let invoice_request = OfferBuilder::new(recipient_pubkey()) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_unchecked_and_sign(); let mut buffer = Vec::new(); @@ -2077,13 +2300,18 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount) + ), } let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .amount_msats_unchecked(999) .build_unchecked_and_sign(); @@ -2092,14 +2320,18 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InsufficientAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InsufficientAmount) + ), } let invoice_request = OfferBuilder::new(recipient_pubkey()) .description("foo".to_string()) .amount(Amount::Currency { iso4217_code: *b"USD", amount: 1000 }) .build_unchecked() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_unchecked_and_sign(); let mut buffer = Vec::new(); @@ -2108,16 +2340,22 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnsupportedCurrency)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnsupportedCurrency) + ); }, } let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .quantity(u64::max_value()).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .quantity(u64::max_value()) + .unwrap() .build_unchecked_and_sign(); let mut buffer = Vec::new(); @@ -2125,7 +2363,10 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount) + ), } } @@ -2143,9 +2384,12 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::One) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -2157,9 +2401,12 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::One) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(2_000).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(2_000) + .unwrap() .quantity_unchecked(2) .build_unchecked_and_sign(); @@ -2169,18 +2416,26 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedQuantity)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedQuantity) + ); }, } let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Bounded(ten)) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(10_000).unwrap() - .quantity(10).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(10_000) + .unwrap() + .quantity(10) + .unwrap() + .build_and_sign() + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -2192,9 +2447,12 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Bounded(ten)) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(11_000).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(11_000) + .unwrap() .quantity_unchecked(11) .build_unchecked_and_sign(); @@ -2203,17 +2461,25 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidQuantity)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidQuantity) + ), } let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .amount_msats(2_000).unwrap() - .quantity(2).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .amount_msats(2_000) + .unwrap() + .quantity(2) + .unwrap() + .build_and_sign() + .unwrap(); let mut buffer = Vec::new(); invoice_request.write(&mut buffer).unwrap(); @@ -2225,8 +2491,10 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_unchecked_and_sign(); let mut buffer = Vec::new(); @@ -2234,14 +2502,19 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingQuantity)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingQuantity) + ), } let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .supported_quantity(Quantity::Bounded(one)) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_unchecked_and_sign(); let mut buffer = Vec::new(); @@ -2249,7 +2522,10 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingQuantity)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingQuantity) + ), } } @@ -2263,8 +2539,10 @@ mod tests { let unsigned_invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_unchecked(); let mut tlv_stream = unsigned_invoice_request.contents.as_tlv_stream(); tlv_stream.0.metadata = None; @@ -2275,7 +2553,10 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerMetadata)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerMetadata) + ); }, } } @@ -2290,8 +2571,10 @@ mod tests { let unsigned_invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_unchecked(); let mut tlv_stream = unsigned_invoice_request.contents.as_tlv_stream(); tlv_stream.2.payer_id = None; @@ -2301,7 +2584,10 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerSigningPubkey)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerSigningPubkey) + ), } } @@ -2315,8 +2601,10 @@ mod tests { let unsigned_invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_unchecked(); let mut tlv_stream = unsigned_invoice_request.contents.as_tlv_stream(); tlv_stream.1.issuer_id = None; @@ -2327,7 +2615,12 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingIssuerSigningPubkey)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics( + Bolt12SemanticError::MissingIssuerSigningPubkey + ) + ); }, } } @@ -2343,15 +2636,21 @@ mod tests { let mut buffer = Vec::new(); OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_unchecked() .contents - .write(&mut buffer).unwrap(); + .write(&mut buffer) + .unwrap(); match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature) + ), } } @@ -2365,9 +2664,12 @@ mod tests { let mut invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); let last_signature_byte = invoice_request.bytes.last_mut().unwrap(); *last_signature_byte = last_signature_byte.wrapping_add(1); @@ -2377,7 +2679,10 @@ mod tests { match InvoiceRequest::try_from(buffer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSignature(secp256k1::Error::IncorrectSignature)); + assert_eq!( + e, + Bolt12ParseError::InvalidSignature(secp256k1::Error::IncorrectSignature) + ); }, } } @@ -2396,8 +2701,10 @@ mod tests { let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let (mut unsigned_invoice_request, payer_keys, _) = OfferBuilder::new(keys.public_key()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_without_checks(); let mut unknown_bytes = Vec::new(); @@ -2411,9 +2718,9 @@ mod tests { let keys = payer_keys.unwrap(); let invoice_request = unsigned_invoice_request - .sign(|message: &UnsignedInvoiceRequest| + .sign(|message: &UnsignedInvoiceRequest| { Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) + }) .unwrap(); let mut encoded_invoice_request = Vec::new(); @@ -2429,8 +2736,10 @@ mod tests { let (mut unsigned_invoice_request, payer_keys, _) = OfferBuilder::new(keys.public_key()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_without_checks(); let mut unknown_bytes = Vec::new(); @@ -2444,9 +2753,9 @@ mod tests { let keys = payer_keys.unwrap(); let invoice_request = unsigned_invoice_request - .sign(|message: &UnsignedInvoiceRequest| + .sign(|message: &UnsignedInvoiceRequest| { Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) + }) .unwrap(); let mut encoded_invoice_request = Vec::new(); @@ -2472,8 +2781,10 @@ mod tests { let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let (mut unsigned_invoice_request, payer_keys, _) = OfferBuilder::new(keys.public_key()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_without_checks(); let mut unknown_bytes = Vec::new(); @@ -2490,9 +2801,9 @@ mod tests { let keys = payer_keys.unwrap(); let invoice_request = unsigned_invoice_request - .sign(|message: &UnsignedInvoiceRequest| + .sign(|message: &UnsignedInvoiceRequest| { Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) + }) .unwrap(); let mut encoded_invoice_request = Vec::new(); @@ -2508,8 +2819,10 @@ mod tests { let (mut unsigned_invoice_request, payer_keys, _) = OfferBuilder::new(keys.public_key()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_without_checks(); let mut unknown_bytes = Vec::new(); @@ -2526,9 +2839,9 @@ mod tests { let keys = payer_keys.unwrap(); let invoice_request = unsigned_invoice_request - .sign(|message: &UnsignedInvoiceRequest| + .sign(|message: &UnsignedInvoiceRequest| { Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &keys)) - ) + }) .unwrap(); let mut encoded_invoice_request = Vec::new(); @@ -2541,9 +2854,12 @@ mod tests { let invoice_request = OfferBuilder::new(keys.public_key()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); let mut encoded_invoice_request = Vec::new(); invoice_request.write(&mut encoded_invoice_request).unwrap(); @@ -2554,7 +2870,10 @@ mod tests { match InvoiceRequest::try_from(encoded_invoice_request) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSignature(secp256k1::Error::IncorrectSignature)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSignature(secp256k1::Error::IncorrectSignature) + ), } } @@ -2568,9 +2887,12 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); let mut encoded_invoice_request = Vec::new(); invoice_request.write(&mut encoded_invoice_request).unwrap(); @@ -2585,7 +2907,9 @@ mod tests { let mut encoded_invoice_request = Vec::new(); invoice_request.write(&mut encoded_invoice_request).unwrap(); - BigSize(EXPERIMENTAL_INVOICE_REQUEST_TYPES.end).write(&mut encoded_invoice_request).unwrap(); + BigSize(EXPERIMENTAL_INVOICE_REQUEST_TYPES.end) + .write(&mut encoded_invoice_request) + .unwrap(); BigSize(32).write(&mut encoded_invoice_request).unwrap(); [42u8; 32].write(&mut encoded_invoice_request).unwrap(); @@ -2610,15 +2934,20 @@ mod tests { .chain(Network::Testnet) .amount_msats(1000) .supported_quantity(Quantity::Unbounded) - .build().unwrap(); + .build() + .unwrap(); assert_eq!(offer.issuer_signing_pubkey(), Some(node_id)); let invoice_request = offer - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .chain(Network::Testnet).unwrap() - .quantity(1).unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .chain(Network::Testnet) + .unwrap() + .quantity(1) + .unwrap() .payer_note("0".repeat(PAYER_NOTE_LIMIT * 2)) - .build_and_sign().unwrap(); + .build_and_sign() + .unwrap(); match invoice_request.verify_using_metadata(&expanded_key, &secp_ctx) { Ok(invoice_request) => { let fields = invoice_request.fields(); From ac632eb502bae47d8f4ed4763501e75371c20a75 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:04 +0100 Subject: [PATCH 07/22] `rustfmt`: Drop `lightning/src/offers/invoice_request.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index b17f38f7dfb..64e701ccf2f 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -38,7 +38,6 @@ lightning/src/ln/script.rs lightning/src/ln/shutdown_tests.rs lightning/src/ln/types.rs lightning/src/ln/wire.rs -lightning/src/offers/invoice_request.rs lightning/src/offers/merkle.rs lightning/src/offers/mod.rs lightning/src/offers/offer.rs From f87eeb930350240ccc88a85c555ebcd4590c60ea Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Mon, 10 Feb 2025 11:24:43 +0100 Subject: [PATCH 08/22] `rustfmt`: Prepare `lightning/src/offers/merkle.rs` --- lightning/src/offers/merkle.rs | 37 ++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/lightning/src/offers/merkle.rs b/lightning/src/offers/merkle.rs index db4f4a41094..789a4c2e963 100644 --- a/lightning/src/offers/merkle.rs +++ b/lightning/src/offers/merkle.rs @@ -308,20 +308,25 @@ mod tests { #[test] fn calculates_merkle_root_hash() { // BOLT 12 test vectors - macro_rules! tlv1 { () => { "010203e8" } } - macro_rules! tlv2 { () => { "02080000010000020003" } } - macro_rules! tlv3 { () => { "03310266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c0351800000000000000010000000000000002" } } + const HEX_1: &'static str = "010203e8"; + let bytes_1 = >::from_hex("b013756c8fee86503a0b4abdab4cddeb1af5d344ca6fc2fa8b6c08938caa6f93").unwrap(); assert_eq!( - super::root_hash(TlvStream::new(&>::from_hex(tlv1!()).unwrap())), - sha256::Hash::from_slice(&>::from_hex("b013756c8fee86503a0b4abdab4cddeb1af5d344ca6fc2fa8b6c08938caa6f93").unwrap()).unwrap(), + super::root_hash(TlvStream::new(&>::from_hex(HEX_1).unwrap())), + sha256::Hash::from_slice(&bytes_1).unwrap(), ); + + const HEX_2: &'static str = concat!("010203e8","02080000010000020003"); + let bytes_2 = >::from_hex("c3774abbf4815aa54ccaa026bff6581f01f3be5fe814c620a252534f434bc0d1").unwrap(); assert_eq!( - super::root_hash(TlvStream::new(&>::from_hex(concat!(tlv1!(), tlv2!())).unwrap())), - sha256::Hash::from_slice(&>::from_hex("c3774abbf4815aa54ccaa026bff6581f01f3be5fe814c620a252534f434bc0d1").unwrap()).unwrap(), + super::root_hash(TlvStream::new(&>::from_hex(HEX_2).unwrap())), + sha256::Hash::from_slice(&bytes_2).unwrap(), ); + + const HEX_3: &'static str = concat!("010203e8","02080000010000020003", "03310266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c0351800000000000000010000000000000002"); + let bytes_3 = >::from_hex("ab2e79b1283b0b31e0b035258de23782df6b89a38cfa7237bde69aed1a658c5d").unwrap(); assert_eq!( - super::root_hash(TlvStream::new(&>::from_hex(concat!(tlv1!(), tlv2!(), tlv3!())).unwrap())), - sha256::Hash::from_slice(&>::from_hex("ab2e79b1283b0b31e0b035258de23782df6b89a38cfa7237bde69aed1a658c5d").unwrap()).unwrap(), + super::root_hash(TlvStream::new(&>::from_hex(HEX_3).unwrap())), + sha256::Hash::from_slice(&bytes_3).unwrap(), ); } @@ -333,11 +338,13 @@ mod tests { let payment_id = PaymentId([1; 32]); let recipient_pubkey = { - let secret_key = SecretKey::from_slice(&>::from_hex("4141414141414141414141414141414141414141414141414141414141414141").unwrap()).unwrap(); + let secret_bytes = >::from_hex("4141414141414141414141414141414141414141414141414141414141414141").unwrap(); + let secret_key = SecretKey::from_slice(&secret_bytes).unwrap(); Keypair::from_secret_key(&secp_ctx, &secret_key).public_key() }; let payer_keys = { - let secret_key = SecretKey::from_slice(&>::from_hex("4242424242424242424242424242424242424242424242424242424242424242").unwrap()).unwrap(); + let secret_bytes = >::from_hex("4242424242424242424242424242424242424242424242424242424242424242").unwrap(); + let secret_key = SecretKey::from_slice(&secret_bytes).unwrap(); Keypair::from_secret_key(&secp_ctx, &secret_key) }; @@ -359,13 +366,17 @@ mod tests { invoice_request.to_string(), "lnr1qqyqqqqqqqqqqqqqqcp4256ypqqkgzshgysy6ct5dpjk6ct5d93kzmpq23ex2ct5d9ek293pqthvwfzadd7jejes8q9lhc4rvjxd022zv5l44g6qah82ru5rdpnpjkppqvjx204vgdzgsqpvcp4mldl3plscny0rt707gvpdh6ndydfacz43euzqhrurageg3n7kafgsek6gz3e9w52parv8gs2hlxzk95tzeswywffxlkeyhml0hh46kndmwf4m6xma3tkq2lu04qz3slje2rfthc89vss", ); + + let bytes = >::from_hex("608407c18ad9a94d9ea2bcdbe170b6c20c462a7833a197621c916f78cf18e624").unwrap(); assert_eq!( super::root_hash(TlvStream::new(&invoice_request.bytes[..])), - sha256::Hash::from_slice(&>::from_hex("608407c18ad9a94d9ea2bcdbe170b6c20c462a7833a197621c916f78cf18e624").unwrap()).unwrap(), + sha256::Hash::from_slice(&bytes).unwrap(), ); + + let bytes = >::from_hex("b8f83ea3288cfd6ea510cdb481472575141e8d8744157f98562d162cc1c472526fdb24befefbdebab4dbb726bbd1b7d8aec057f8fa805187e5950d2bbe0e5642").unwrap(); assert_eq!( invoice_request.signature(), - Signature::from_slice(&>::from_hex("b8f83ea3288cfd6ea510cdb481472575141e8d8744157f98562d162cc1c472526fdb24befefbdebab4dbb726bbd1b7d8aec057f8fa805187e5950d2bbe0e5642").unwrap()).unwrap(), + Signature::from_slice(&bytes).unwrap(), ); } From 01702f57908f00522e0182787c60ee9f4cee02e6 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:11 +0100 Subject: [PATCH 09/22] `rustfmt`: Run on `lightning/src/offers/merkle.rs` --- lightning/src/offers/merkle.rs | 96 +++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 42 deletions(-) diff --git a/lightning/src/offers/merkle.rs b/lightning/src/offers/merkle.rs index 789a4c2e963..3c84e7a7a17 100644 --- a/lightning/src/offers/merkle.rs +++ b/lightning/src/offers/merkle.rs @@ -9,11 +9,11 @@ //! Tagged hashes for use in signature calculation and verification. -use bitcoin::hashes::{Hash, HashEngine, sha256}; -use bitcoin::secp256k1::{Message, PublicKey, Secp256k1, self}; -use bitcoin::secp256k1::schnorr::Signature; use crate::io; use crate::util::ser::{BigSize, Readable, Writeable, Writer}; +use bitcoin::hashes::{sha256, Hash, HashEngine}; +use bitcoin::secp256k1::schnorr::Signature; +use bitcoin::secp256k1::{self, Message, PublicKey, Secp256k1}; #[allow(unused_imports)] use crate::prelude::*; @@ -50,16 +50,12 @@ impl TaggedHash { /// /// Panics if `tlv_stream` is not a well-formed TLV stream containing at least one TLV record. pub(super) fn from_tlv_stream<'a, I: core::iter::Iterator>>( - tag: &'static str, tlv_stream: I + tag: &'static str, tlv_stream: I, ) -> Self { let tag_hash = sha256::Hash::hash(tag.as_bytes()); let merkle_root = root_hash(tlv_stream); let digest = Message::from_digest(tagged_hash(tag_hash, merkle_root).to_byte_array()); - Self { - tag, - merkle_root, - digest, - } + Self { tag, merkle_root, digest } } /// Returns the digest to sign. @@ -227,9 +223,7 @@ pub(super) struct TlvStream<'a> { impl<'a> TlvStream<'a> { pub fn new(data: &'a [u8]) -> Self { - Self { - data: io::Cursor::new(data), - } + Self { data: io::Cursor::new(data) } } pub fn range(self, types: T) -> impl core::iter::Iterator> @@ -271,9 +265,7 @@ impl<'a> Iterator for TlvStream<'a> { self.data.set_position(end); - Some(TlvRecord { - r#type, type_bytes, record_bytes, end: end as usize, - }) + Some(TlvRecord { r#type, type_bytes, record_bytes, end: end as usize }) } else { None } @@ -289,41 +281,47 @@ impl<'a> Writeable for TlvRecord<'a> { #[cfg(test)] mod tests { - use super::{SIGNATURE_TYPES, TlvStream}; + use super::{TlvStream, SIGNATURE_TYPES}; - use bitcoin::hashes::{Hash, sha256}; - use bitcoin::hex::FromHex; - use bitcoin::secp256k1::{Keypair, Message, Secp256k1, SecretKey}; - use bitcoin::secp256k1::schnorr::Signature; use crate::ln::channelmanager::PaymentId; use crate::ln::inbound_payment::ExpandedKey; + use crate::offers::invoice_request::{InvoiceRequest, UnsignedInvoiceRequest}; use crate::offers::nonce::Nonce; use crate::offers::offer::{Amount, OfferBuilder}; - use crate::offers::invoice_request::{InvoiceRequest, UnsignedInvoiceRequest}; use crate::offers::parse::Bech32Encode; use crate::offers::signer::Metadata; use crate::offers::test_utils::recipient_pubkey; use crate::util::ser::Writeable; + use bitcoin::hashes::{sha256, Hash}; + use bitcoin::hex::FromHex; + use bitcoin::secp256k1::schnorr::Signature; + use bitcoin::secp256k1::{Keypair, Message, Secp256k1, SecretKey}; #[test] fn calculates_merkle_root_hash() { // BOLT 12 test vectors const HEX_1: &'static str = "010203e8"; - let bytes_1 = >::from_hex("b013756c8fee86503a0b4abdab4cddeb1af5d344ca6fc2fa8b6c08938caa6f93").unwrap(); + let bytes_1 = + >::from_hex("b013756c8fee86503a0b4abdab4cddeb1af5d344ca6fc2fa8b6c08938caa6f93") + .unwrap(); assert_eq!( super::root_hash(TlvStream::new(&>::from_hex(HEX_1).unwrap())), sha256::Hash::from_slice(&bytes_1).unwrap(), ); - const HEX_2: &'static str = concat!("010203e8","02080000010000020003"); - let bytes_2 = >::from_hex("c3774abbf4815aa54ccaa026bff6581f01f3be5fe814c620a252534f434bc0d1").unwrap(); + const HEX_2: &'static str = concat!("010203e8", "02080000010000020003"); + let bytes_2 = + >::from_hex("c3774abbf4815aa54ccaa026bff6581f01f3be5fe814c620a252534f434bc0d1") + .unwrap(); assert_eq!( super::root_hash(TlvStream::new(&>::from_hex(HEX_2).unwrap())), sha256::Hash::from_slice(&bytes_2).unwrap(), ); const HEX_3: &'static str = concat!("010203e8","02080000010000020003", "03310266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c0351800000000000000010000000000000002"); - let bytes_3 = >::from_hex("ab2e79b1283b0b31e0b035258de23782df6b89a38cfa7237bde69aed1a658c5d").unwrap(); + let bytes_3 = + >::from_hex("ab2e79b1283b0b31e0b035258de23782df6b89a38cfa7237bde69aed1a658c5d") + .unwrap(); assert_eq!( super::root_hash(TlvStream::new(&>::from_hex(HEX_3).unwrap())), sha256::Hash::from_slice(&bytes_3).unwrap(), @@ -338,12 +336,18 @@ mod tests { let payment_id = PaymentId([1; 32]); let recipient_pubkey = { - let secret_bytes = >::from_hex("4141414141414141414141414141414141414141414141414141414141414141").unwrap(); + let secret_bytes = >::from_hex( + "4141414141414141414141414141414141414141414141414141414141414141", + ) + .unwrap(); let secret_key = SecretKey::from_slice(&secret_bytes).unwrap(); Keypair::from_secret_key(&secp_ctx, &secret_key).public_key() }; let payer_keys = { - let secret_bytes = >::from_hex("4242424242424242424242424242424242424242424242424242424242424242").unwrap(); + let secret_bytes = >::from_hex( + "4242424242424242424242424242424242424242424242424242424242424242", + ) + .unwrap(); let secret_key = SecretKey::from_slice(&secret_bytes).unwrap(); Keypair::from_secret_key(&secp_ctx, &secret_key) }; @@ -354,30 +358,30 @@ mod tests { .amount(Amount::Currency { iso4217_code: *b"USD", amount: 100 }) .build_unchecked() // Override the payer metadata and signing pubkey to match the test vectors - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .payer_metadata(Metadata::Bytes(vec![0; 8])) .payer_signing_pubkey(payer_keys.public_key()) .build_unchecked() - .sign(|message: &UnsignedInvoiceRequest| + .sign(|message: &UnsignedInvoiceRequest| { Ok(secp_ctx.sign_schnorr_no_aux_rand(message.as_ref().as_digest(), &payer_keys)) - ) + }) .unwrap(); assert_eq!( invoice_request.to_string(), "lnr1qqyqqqqqqqqqqqqqqcp4256ypqqkgzshgysy6ct5dpjk6ct5d93kzmpq23ex2ct5d9ek293pqthvwfzadd7jejes8q9lhc4rvjxd022zv5l44g6qah82ru5rdpnpjkppqvjx204vgdzgsqpvcp4mldl3plscny0rt707gvpdh6ndydfacz43euzqhrurageg3n7kafgsek6gz3e9w52parv8gs2hlxzk95tzeswywffxlkeyhml0hh46kndmwf4m6xma3tkq2lu04qz3slje2rfthc89vss", ); - let bytes = >::from_hex("608407c18ad9a94d9ea2bcdbe170b6c20c462a7833a197621c916f78cf18e624").unwrap(); + let bytes = + >::from_hex("608407c18ad9a94d9ea2bcdbe170b6c20c462a7833a197621c916f78cf18e624") + .unwrap(); assert_eq!( super::root_hash(TlvStream::new(&invoice_request.bytes[..])), sha256::Hash::from_slice(&bytes).unwrap(), ); let bytes = >::from_hex("b8f83ea3288cfd6ea510cdb481472575141e8d8744157f98562d162cc1c472526fdb24befefbdebab4dbb726bbd1b7d8aec057f8fa805187e5950d2bbe0e5642").unwrap(); - assert_eq!( - invoice_request.signature(), - Signature::from_slice(&bytes).unwrap(), - ); + assert_eq!(invoice_request.signature(), Signature::from_slice(&bytes).unwrap(),); } #[test] @@ -389,8 +393,10 @@ mod tests { let unsigned_invoice_request = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) - .build().unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .build() + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .payer_note("bar".into()) .build_unchecked(); @@ -399,7 +405,9 @@ mod tests { let tagged_hash = unsigned_invoice_request.as_ref(); let expected_digest = unsigned_invoice_request.as_ref().as_digest(); let tag = sha256::Hash::hash(tagged_hash.tag().as_bytes()); - let actual_digest = Message::from_digest(super::tagged_hash(tag, tagged_hash.merkle_root()).to_byte_array()); + let actual_digest = Message::from_digest( + super::tagged_hash(tag, tagged_hash.merkle_root()).to_byte_array(), + ); assert_eq!(*expected_digest, actual_digest); } @@ -418,8 +426,10 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey) .amount_msats(100) .build_unchecked() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); let mut bytes_without_signature = Vec::new(); let tlv_stream_without_signatures = TlvStream::new(&invoice_request.bytes) @@ -450,11 +460,13 @@ mod tests { let invoice_request = OfferBuilder::new(recipient_pubkey) .amount_msats(100) .build_unchecked() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() .build_and_sign() .unwrap(); - let tlv_stream = TlvStream::new(&invoice_request.bytes).range(0..1) + let tlv_stream = TlvStream::new(&invoice_request.bytes) + .range(0..1) .chain(TlvStream::new(&invoice_request.bytes).range(1..80)) .chain(TlvStream::new(&invoice_request.bytes).range(80..160)) .chain(TlvStream::new(&invoice_request.bytes).range(160..240)) From 747dc4d9f27d77320f28224ff3e6c389ced13ce1 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:11 +0100 Subject: [PATCH 10/22] `rustfmt`: Drop `lightning/src/offers/merkle.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index 64e701ccf2f..1304602f036 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -38,7 +38,6 @@ lightning/src/ln/script.rs lightning/src/ln/shutdown_tests.rs lightning/src/ln/types.rs lightning/src/ln/wire.rs -lightning/src/offers/merkle.rs lightning/src/offers/mod.rs lightning/src/offers/offer.rs lightning/src/offers/parse.rs From a439e00eaf0193c45303461afc42231ae918c863 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:22 +0100 Subject: [PATCH 11/22] `rustfmt`: Run on `lightning/src/offers/offer.rs` --- lightning/src/offers/offer.rs | 566 +++++++++++++++++++--------------- 1 file changed, 320 insertions(+), 246 deletions(-) diff --git a/lightning/src/offers/offer.rs b/lightning/src/offers/offer.rs index 0cd1cece6b7..e9a2d9428e2 100644 --- a/lightning/src/offers/offer.rs +++ b/lightning/src/offers/offer.rs @@ -77,42 +77,40 @@ //! [`ChannelManager`]: crate::ln::channelmanager::ChannelManager //! [`ChannelManager::create_offer_builder`]: crate::ln::channelmanager::ChannelManager::create_offer_builder -use core::borrow::Borrow; -use bitcoin::constants::ChainHash; -use bitcoin::network::Network; -use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, self}; -use core::hash::{Hash, Hasher}; -use core::num::NonZeroU64; -use core::str::FromStr; -use core::time::Duration; -use crate::io; use crate::blinded_path::message::BlindedMessagePath; +use crate::io; use crate::ln::channelmanager::PaymentId; -use crate::types::features::OfferFeatures; use crate::ln::inbound_payment::{ExpandedKey, IV_LEN}; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; use crate::offers::merkle::{TaggedHash, TlvRecord, TlvStream}; use crate::offers::nonce::Nonce; use crate::offers::parse::{Bech32Encode, Bolt12ParseError, Bolt12SemanticError, ParsedMessage}; -use crate::offers::signer::{Metadata, MetadataMaterial, self}; -use crate::util::ser::{CursorReadable, HighZeroBytesDroppedBigSize, Readable, WithoutLength, Writeable, Writer}; +use crate::offers::signer::{self, Metadata, MetadataMaterial}; +use crate::types::features::OfferFeatures; +use crate::util::ser::{ + CursorReadable, HighZeroBytesDroppedBigSize, Readable, WithoutLength, Writeable, Writer, +}; use crate::util::string::PrintableString; +use bitcoin::constants::ChainHash; +use bitcoin::network::Network; +use bitcoin::secp256k1::{self, Keypair, PublicKey, Secp256k1}; +use core::borrow::Borrow; +use core::hash::{Hash, Hasher}; +use core::num::NonZeroU64; +use core::str::FromStr; +use core::time::Duration; #[cfg(not(c_bindings))] -use { - crate::offers::invoice_request::InvoiceRequestBuilder, -}; +use crate::offers::invoice_request::InvoiceRequestBuilder; #[cfg(c_bindings)] -use { - crate::offers::invoice_request::InvoiceRequestWithDerivedPayerSigningPubkeyBuilder, -}; +use crate::offers::invoice_request::InvoiceRequestWithDerivedPayerSigningPubkeyBuilder; #[allow(unused_imports)] use crate::prelude::*; +use bitcoin::hex::impl_fmt_traits; #[cfg(feature = "std")] use std::time::SystemTime; -use bitcoin::hex::impl_fmt_traits; pub(super) const IV_BYTES_WITH_METADATA: &[u8; IV_LEN] = b"LDK Offer ~~~~~~"; pub(super) const IV_BYTES_WITHOUT_METADATA: &[u8; IV_LEN] = b"LDK Offer v2~~~~"; @@ -218,78 +216,98 @@ impl MetadataStrategy for ExplicitMetadata {} impl MetadataStrategy for DerivedMetadata {} -macro_rules! offer_explicit_metadata_builder_methods { ( +macro_rules! offer_explicit_metadata_builder_methods { + ( $self: ident, $self_type: ty, $return_type: ty, $return_value: expr ) => { - /// Creates a new builder for an offer using the `signing_pubkey` for signing invoices. The - /// associated secret key must be remembered while the offer is valid. - /// - /// Use a different pubkey per offer to avoid correlating offers. - /// - /// # Note - /// - /// If constructing an [`Offer`] for use with a [`ChannelManager`], use - /// [`ChannelManager::create_offer_builder`] instead of [`OfferBuilder::new`]. - /// - /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager - /// [`ChannelManager::create_offer_builder`]: crate::ln::channelmanager::ChannelManager::create_offer_builder - pub fn new(signing_pubkey: PublicKey) -> Self { - Self { - offer: OfferContents { - chains: None, metadata: None, amount: None, description: None, - features: OfferFeatures::empty(), absolute_expiry: None, issuer: None, paths: None, - supported_quantity: Quantity::One, issuer_signing_pubkey: Some(signing_pubkey), - #[cfg(test)] - experimental_foo: None, - }, - metadata_strategy: core::marker::PhantomData, - secp_ctx: None, + /// Creates a new builder for an offer using the `signing_pubkey` for signing invoices. The + /// associated secret key must be remembered while the offer is valid. + /// + /// Use a different pubkey per offer to avoid correlating offers. + /// + /// # Note + /// + /// If constructing an [`Offer`] for use with a [`ChannelManager`], use + /// [`ChannelManager::create_offer_builder`] instead of [`OfferBuilder::new`]. + /// + /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager + /// [`ChannelManager::create_offer_builder`]: crate::ln::channelmanager::ChannelManager::create_offer_builder + pub fn new(signing_pubkey: PublicKey) -> Self { + Self { + offer: OfferContents { + chains: None, + metadata: None, + amount: None, + description: None, + features: OfferFeatures::empty(), + absolute_expiry: None, + issuer: None, + paths: None, + supported_quantity: Quantity::One, + issuer_signing_pubkey: Some(signing_pubkey), + #[cfg(test)] + experimental_foo: None, + }, + metadata_strategy: core::marker::PhantomData, + secp_ctx: None, + } } - } - /// Sets the [`Offer::metadata`] to the given bytes. - /// - /// Successive calls to this method will override the previous setting. - pub fn metadata(mut $self: $self_type, metadata: Vec) -> Result<$return_type, Bolt12SemanticError> { - $self.offer.metadata = Some(Metadata::Bytes(metadata)); - Ok($return_value) - } -} } + /// Sets the [`Offer::metadata`] to the given bytes. + /// + /// Successive calls to this method will override the previous setting. + pub fn metadata( + mut $self: $self_type, metadata: Vec, + ) -> Result<$return_type, Bolt12SemanticError> { + $self.offer.metadata = Some(Metadata::Bytes(metadata)); + Ok($return_value) + } + }; +} -macro_rules! offer_derived_metadata_builder_methods { ($secp_context: ty) => { - /// Similar to [`OfferBuilder::new`] except, if [`OfferBuilder::path`] is called, the signing - /// pubkey is derived from the given [`ExpandedKey`] and [`Nonce`]. This provides recipient - /// privacy by using a different signing pubkey for each offer. Otherwise, the provided - /// `node_id` is used for [`Offer::issuer_signing_pubkey`]. - /// - /// Also, sets the metadata when [`OfferBuilder::build`] is called such that it can be used by - /// [`InvoiceRequest::verify_using_metadata`] to determine if the request was produced for the - /// offer given an [`ExpandedKey`]. However, if [`OfferBuilder::path`] is called, then the - /// metadata will not be set and must be included in each [`BlindedMessagePath`] instead. In this case, - /// use [`InvoiceRequest::verify_using_recipient_data`]. - /// - /// [`InvoiceRequest::verify_using_metadata`]: crate::offers::invoice_request::InvoiceRequest::verify_using_metadata - /// [`InvoiceRequest::verify_using_recipient_data`]: crate::offers::invoice_request::InvoiceRequest::verify_using_recipient_data - /// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey - pub fn deriving_signing_pubkey( - node_id: PublicKey, expanded_key: &ExpandedKey, nonce: Nonce, - secp_ctx: &'a Secp256k1<$secp_context> - ) -> Self { - let derivation_material = MetadataMaterial::new(nonce, expanded_key, None); - let metadata = Metadata::DerivedSigningPubkey(derivation_material); - Self { - offer: OfferContents { - chains: None, metadata: Some(metadata), amount: None, description: None, - features: OfferFeatures::empty(), absolute_expiry: None, issuer: None, paths: None, - supported_quantity: Quantity::One, issuer_signing_pubkey: Some(node_id), - #[cfg(test)] - experimental_foo: None, - }, - metadata_strategy: core::marker::PhantomData, - secp_ctx: Some(secp_ctx), +macro_rules! offer_derived_metadata_builder_methods { + ($secp_context: ty) => { + /// Similar to [`OfferBuilder::new`] except, if [`OfferBuilder::path`] is called, the signing + /// pubkey is derived from the given [`ExpandedKey`] and [`Nonce`]. This provides recipient + /// privacy by using a different signing pubkey for each offer. Otherwise, the provided + /// `node_id` is used for [`Offer::issuer_signing_pubkey`]. + /// + /// Also, sets the metadata when [`OfferBuilder::build`] is called such that it can be used by + /// [`InvoiceRequest::verify_using_metadata`] to determine if the request was produced for the + /// offer given an [`ExpandedKey`]. However, if [`OfferBuilder::path`] is called, then the + /// metadata will not be set and must be included in each [`BlindedMessagePath`] instead. In this case, + /// use [`InvoiceRequest::verify_using_recipient_data`]. + /// + /// [`InvoiceRequest::verify_using_metadata`]: crate::offers::invoice_request::InvoiceRequest::verify_using_metadata + /// [`InvoiceRequest::verify_using_recipient_data`]: crate::offers::invoice_request::InvoiceRequest::verify_using_recipient_data + /// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey + pub fn deriving_signing_pubkey( + node_id: PublicKey, expanded_key: &ExpandedKey, nonce: Nonce, + secp_ctx: &'a Secp256k1<$secp_context>, + ) -> Self { + let derivation_material = MetadataMaterial::new(nonce, expanded_key, None); + let metadata = Metadata::DerivedSigningPubkey(derivation_material); + Self { + offer: OfferContents { + chains: None, + metadata: Some(metadata), + amount: None, + description: None, + features: OfferFeatures::empty(), + absolute_expiry: None, + issuer: None, + paths: None, + supported_quantity: Quantity::One, + issuer_signing_pubkey: Some(node_id), + #[cfg(test)] + experimental_foo: None, + }, + metadata_strategy: core::marker::PhantomData, + secp_ctx: Some(secp_ctx), + } } - } -} } + }; +} macro_rules! offer_builder_methods { ( $self: ident, $self_type: ty, $return_type: ty, $return_value: expr $(, $self_mut: tt)? @@ -538,7 +556,8 @@ impl<'a> OfferWithDerivedMetadataBuilder<'a> { #[cfg(c_bindings)] impl<'a> From> -for OfferWithDerivedMetadataBuilder<'a> { + for OfferWithDerivedMetadataBuilder<'a> +{ fn from(builder: OfferBuilder<'a, DerivedMetadata, secp256k1::All>) -> Self { let OfferBuilder { offer, metadata_strategy, secp_ctx } = builder; @@ -548,7 +567,8 @@ for OfferWithDerivedMetadataBuilder<'a> { #[cfg(c_bindings)] impl<'a> From> -for OfferBuilder<'a, DerivedMetadata, secp256k1::All> { + for OfferBuilder<'a, DerivedMetadata, secp256k1::All> +{ fn from(builder: OfferWithDerivedMetadataBuilder<'a>) -> Self { let OfferWithDerivedMetadataBuilder { offer, metadata_strategy, secp_ctx } = builder; @@ -715,15 +735,16 @@ impl Offer { } pub(super) fn tlv_stream_iter<'a>( - bytes: &'a [u8] + bytes: &'a [u8], ) -> impl core::iter::Iterator> { - TlvStream::new(bytes).range(OFFER_TYPES) + TlvStream::new(bytes) + .range(OFFER_TYPES) .chain(TlvStream::new(bytes).range(EXPERIMENTAL_OFFER_TYPES)) } #[cfg(async_payments)] pub(super) fn verify( - &self, nonce: Nonce, key: &ExpandedKey, secp_ctx: &Secp256k1 + &self, nonce: Nonce, key: &ExpandedKey, secp_ctx: &Secp256k1, ) -> Result<(OfferId, Option), ()> { self.contents.verify_using_recipient_data(&self.bytes, nonce, key, secp_ctx) } @@ -773,7 +794,10 @@ impl Offer { #[cfg(c_bindings)] impl Offer { - request_invoice_derived_signing_pubkey!(self, InvoiceRequestWithDerivedPayerSigningPubkeyBuilder<'a, 'b>); + request_invoice_derived_signing_pubkey!( + self, + InvoiceRequestWithDerivedPayerSigningPubkeyBuilder<'a, 'b> + ); } #[cfg(test)] @@ -859,7 +883,7 @@ impl OfferContents { } pub(super) fn check_amount_msats_for_quantity( - &self, amount_msats: Option, quantity: Option + &self, amount_msats: Option, quantity: Option, ) -> Result<(), Bolt12SemanticError> { let offer_amount_msats = match self.amount { None => 0, @@ -868,7 +892,8 @@ impl OfferContents { }; if !self.expects_quantity() || quantity.is_some() { - let expected_amount_msats = offer_amount_msats.checked_mul(quantity.unwrap_or(1)) + let expected_amount_msats = offer_amount_msats + .checked_mul(quantity.unwrap_or(1)) .ok_or(Bolt12SemanticError::InvalidAmount)?; let amount_msats = amount_msats.unwrap_or(expected_amount_msats); @@ -921,13 +946,13 @@ impl OfferContents { } pub(super) fn verify_using_metadata( - &self, bytes: &[u8], key: &ExpandedKey, secp_ctx: &Secp256k1 + &self, bytes: &[u8], key: &ExpandedKey, secp_ctx: &Secp256k1, ) -> Result<(OfferId, Option), ()> { self.verify(bytes, self.metadata.as_ref(), key, IV_BYTES_WITH_METADATA, secp_ctx) } pub(super) fn verify_using_recipient_data( - &self, bytes: &[u8], nonce: Nonce, key: &ExpandedKey, secp_ctx: &Secp256k1 + &self, bytes: &[u8], nonce: Nonce, key: &ExpandedKey, secp_ctx: &Secp256k1, ) -> Result<(OfferId, Option), ()> { let metadata = Metadata::RecipientData(nonce); self.verify(bytes, Some(&metadata), key, IV_BYTES_WITHOUT_METADATA, secp_ctx) @@ -936,25 +961,30 @@ impl OfferContents { /// Verifies that the offer metadata was produced from the offer in the TLV stream. fn verify( &self, bytes: &[u8], metadata: Option<&Metadata>, key: &ExpandedKey, - iv_bytes: &[u8; IV_LEN], secp_ctx: &Secp256k1 + iv_bytes: &[u8; IV_LEN], secp_ctx: &Secp256k1, ) -> Result<(OfferId, Option), ()> { match metadata { Some(metadata) => { - let tlv_stream = TlvStream::new(bytes).range(OFFER_TYPES).filter(|record| { - match record.r#type { + let tlv_stream = TlvStream::new(bytes) + .range(OFFER_TYPES) + .filter(|record| match record.r#type { OFFER_METADATA_TYPE => false, OFFER_ISSUER_ID_TYPE => !metadata.derives_recipient_keys(), _ => true, - } - }) - .chain(TlvStream::new(bytes).range(EXPERIMENTAL_OFFER_TYPES)); + }) + .chain(TlvStream::new(bytes).range(EXPERIMENTAL_OFFER_TYPES)); let signing_pubkey = match self.issuer_signing_pubkey() { Some(signing_pubkey) => signing_pubkey, None => return Err(()), }; let keys = signer::verify_recipient_metadata( - metadata.as_ref(), key, iv_bytes, signing_pubkey, tlv_stream, secp_ctx + metadata.as_ref(), + key, + iv_bytes, + signing_pubkey, + tlv_stream, + secp_ctx, )?; let offer_id = OfferId::from_valid_invreq_tlv_stream(bytes); @@ -969,13 +999,15 @@ impl OfferContents { let (currency, amount) = match &self.amount { None => (None, None), Some(Amount::Bitcoin { amount_msats }) => (None, Some(*amount_msats)), - Some(Amount::Currency { iso4217_code, amount }) => ( - Some(iso4217_code), Some(*amount) - ), + Some(Amount::Currency { iso4217_code, amount }) => (Some(iso4217_code), Some(*amount)), }; let features = { - if self.features == OfferFeatures::empty() { None } else { Some(&self.features) } + if self.features == OfferFeatures::empty() { + None + } else { + Some(&self.features) + } }; let offer = OfferTlvStreamRef { @@ -1145,8 +1177,17 @@ impl TryFrom for OfferContents { fn try_from(tlv_stream: FullOfferTlvStream) -> Result { let ( OfferTlvStream { - chains, metadata, currency, amount, description, features, absolute_expiry, paths, - issuer, quantity_max, issuer_id, + chains, + metadata, + currency, + amount, + description, + features, + absolute_expiry, + paths, + issuer, + quantity_max, + issuer_id, }, ExperimentalOfferTlvStream { #[cfg(test)] @@ -1172,8 +1213,8 @@ impl TryFrom for OfferContents { let features = features.unwrap_or_else(OfferFeatures::empty); - let absolute_expiry = absolute_expiry - .map(|seconds_from_epoch| Duration::from_secs(seconds_from_epoch)); + let absolute_expiry = + absolute_expiry.map(|seconds_from_epoch| Duration::from_secs(seconds_from_epoch)); let supported_quantity = match quantity_max { None => Quantity::One, @@ -1188,8 +1229,16 @@ impl TryFrom for OfferContents { }; Ok(OfferContents { - chains, metadata, amount, description, features, absolute_expiry, issuer, paths, - supported_quantity, issuer_signing_pubkey, + chains, + metadata, + amount, + description, + features, + absolute_expiry, + issuer, + paths, + supported_quantity, + issuer_signing_pubkey, #[cfg(test)] experimental_foo, }) @@ -1204,32 +1253,31 @@ impl core::fmt::Display for Offer { #[cfg(test)] mod tests { - use super::{Amount, EXPERIMENTAL_OFFER_TYPES, ExperimentalOfferTlvStreamRef, OFFER_TYPES, Offer, OfferTlvStreamRef, Quantity}; #[cfg(not(c_bindings))] - use { - super::OfferBuilder, - }; + use super::OfferBuilder; #[cfg(c_bindings)] - use { - super::OfferWithExplicitMetadataBuilder as OfferBuilder, + use super::OfferWithExplicitMetadataBuilder as OfferBuilder; + use super::{ + Amount, ExperimentalOfferTlvStreamRef, Offer, OfferTlvStreamRef, Quantity, + EXPERIMENTAL_OFFER_TYPES, OFFER_TYPES, }; - use bitcoin::constants::ChainHash; - use bitcoin::network::Network; - use bitcoin::secp256k1::Secp256k1; - use core::num::NonZeroU64; - use core::time::Duration; - use crate::blinded_path::BlindedHop; use crate::blinded_path::message::BlindedMessagePath; - use crate::types::features::OfferFeatures; + use crate::blinded_path::BlindedHop; use crate::ln::channelmanager::PaymentId; use crate::ln::inbound_payment::ExpandedKey; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; use crate::offers::nonce::Nonce; use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError}; use crate::offers::test_utils::*; + use crate::types::features::OfferFeatures; use crate::util::ser::{BigSize, Writeable}; use crate::util::string::PrintableString; + use bitcoin::constants::ChainHash; + use bitcoin::network::Network; + use bitcoin::secp256k1::Secp256k1; + use core::num::NonZeroU64; + use core::time::Duration; #[test] fn builds_offer_with_defaults() { @@ -1270,9 +1318,7 @@ mod tests { quantity_max: None, issuer_id: Some(&pubkey(42)), }, - ExperimentalOfferTlvStreamRef { - experimental_foo: None, - }, + ExperimentalOfferTlvStreamRef { experimental_foo: None }, ), ); @@ -1286,18 +1332,12 @@ mod tests { let mainnet = ChainHash::using_genesis_block(Network::Bitcoin); let testnet = ChainHash::using_genesis_block(Network::Testnet); - let offer = OfferBuilder::new(pubkey(42)) - .chain(Network::Bitcoin) - .build() - .unwrap(); + let offer = OfferBuilder::new(pubkey(42)).chain(Network::Bitcoin).build().unwrap(); assert!(offer.supports_chain(mainnet)); assert_eq!(offer.chains(), vec![mainnet]); assert_eq!(offer.as_tlv_stream().0.chains, None); - let offer = OfferBuilder::new(pubkey(42)) - .chain(Network::Testnet) - .build() - .unwrap(); + let offer = OfferBuilder::new(pubkey(42)).chain(Network::Testnet).build().unwrap(); assert!(offer.supports_chain(testnet)); assert_eq!(offer.chains(), vec![testnet]); assert_eq!(offer.as_tlv_stream().0.chains, Some(&vec![testnet])); @@ -1324,16 +1364,15 @@ mod tests { #[test] fn builds_offer_with_metadata() { - let offer = OfferBuilder::new(pubkey(42)) - .metadata(vec![42; 32]).unwrap() - .build() - .unwrap(); + let offer = OfferBuilder::new(pubkey(42)).metadata(vec![42; 32]).unwrap().build().unwrap(); assert_eq!(offer.metadata(), Some(&vec![42; 32])); assert_eq!(offer.as_tlv_stream().0.metadata, Some(&vec![42; 32])); let offer = OfferBuilder::new(pubkey(42)) - .metadata(vec![42; 32]).unwrap() - .metadata(vec![43; 32]).unwrap() + .metadata(vec![42; 32]) + .unwrap() + .metadata(vec![43; 32]) + .unwrap() .build() .unwrap(); assert_eq!(offer.metadata(), Some(&vec![43; 32])); @@ -1354,13 +1393,16 @@ mod tests { let offer = OfferBuilder::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx) .amount_msats(1000) .experimental_foo(42) - .build().unwrap(); + .build() + .unwrap(); assert!(offer.metadata().is_some()); assert_eq!(offer.issuer_signing_pubkey(), Some(node_id)); let invoice_request = offer - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); match invoice_request.verify_using_metadata(&expanded_key, &secp_ctx) { Ok(invoice_request) => assert_eq!(invoice_request.offer_id, offer.id()), Err(_) => panic!("unexpected error"), @@ -1368,11 +1410,13 @@ mod tests { // Fails verification when using the wrong method let invoice_request = offer - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); - assert!( - invoice_request.verify_using_recipient_data(nonce, &expanded_key, &secp_ctx).is_err() - ); + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); + assert!(invoice_request + .verify_using_recipient_data(nonce, &expanded_key, &secp_ctx) + .is_err()); // Fails verification with altered offer field let mut tlv_stream = offer.as_tlv_stream(); @@ -1381,9 +1425,12 @@ mod tests { let mut encoded_offer = Vec::new(); tlv_stream.write(&mut encoded_offer).unwrap(); - let invoice_request = Offer::try_from(encoded_offer).unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + let invoice_request = Offer::try_from(encoded_offer) + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); assert!(invoice_request.verify_using_metadata(&expanded_key, &secp_ctx).is_err()); // Fails verification with altered metadata @@ -1394,9 +1441,12 @@ mod tests { let mut encoded_offer = Vec::new(); tlv_stream.write(&mut encoded_offer).unwrap(); - let invoice_request = Offer::try_from(encoded_offer).unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + let invoice_request = Offer::try_from(encoded_offer) + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); assert!(invoice_request.verify_using_metadata(&expanded_key, &secp_ctx).is_err()); } @@ -1410,11 +1460,12 @@ mod tests { let payment_id = PaymentId([1; 32]); let blinded_path = BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(42), encrypted_payload: vec![0; 43] }, BlindedHop { blinded_node_id: node_id, encrypted_payload: vec![0; 44] }, - ] + ], ); #[cfg(c_bindings)] @@ -1423,13 +1474,16 @@ mod tests { .amount_msats(1000) .path(blinded_path) .experimental_foo(42) - .build().unwrap(); + .build() + .unwrap(); assert!(offer.metadata().is_none()); assert_ne!(offer.issuer_signing_pubkey(), Some(node_id)); let invoice_request = offer - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); match invoice_request.verify_using_recipient_data(nonce, &expanded_key, &secp_ctx) { Ok(invoice_request) => assert_eq!(invoice_request.offer_id, offer.id()), Err(_) => panic!("unexpected error"), @@ -1437,8 +1491,10 @@ mod tests { // Fails verification when using the wrong method let invoice_request = offer - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); assert!(invoice_request.verify_using_metadata(&expanded_key, &secp_ctx).is_err()); // Fails verification with altered offer field @@ -1448,12 +1504,15 @@ mod tests { let mut encoded_offer = Vec::new(); tlv_stream.write(&mut encoded_offer).unwrap(); - let invoice_request = Offer::try_from(encoded_offer).unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); - assert!( - invoice_request.verify_using_recipient_data(nonce, &expanded_key, &secp_ctx).is_err() - ); + let invoice_request = Offer::try_from(encoded_offer) + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); + assert!(invoice_request + .verify_using_recipient_data(nonce, &expanded_key, &secp_ctx) + .is_err()); // Fails verification with altered signing pubkey let mut tlv_stream = offer.as_tlv_stream(); @@ -1463,12 +1522,15 @@ mod tests { let mut encoded_offer = Vec::new(); tlv_stream.write(&mut encoded_offer).unwrap(); - let invoice_request = Offer::try_from(encoded_offer).unwrap() - .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id).unwrap() - .build_and_sign().unwrap(); - assert!( - invoice_request.verify_using_recipient_data(nonce, &expanded_key, &secp_ctx).is_err() - ); + let invoice_request = Offer::try_from(encoded_offer) + .unwrap() + .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) + .unwrap() + .build_and_sign() + .unwrap(); + assert!(invoice_request + .verify_using_recipient_data(nonce, &expanded_key, &secp_ctx) + .is_err()); } #[test] @@ -1476,18 +1538,14 @@ mod tests { let bitcoin_amount = Amount::Bitcoin { amount_msats: 1000 }; let currency_amount = Amount::Currency { iso4217_code: *b"USD", amount: 10 }; - let offer = OfferBuilder::new(pubkey(42)) - .amount_msats(1000) - .build() - .unwrap(); + let offer = OfferBuilder::new(pubkey(42)).amount_msats(1000).build().unwrap(); let tlv_stream = offer.as_tlv_stream(); assert_eq!(offer.amount(), Some(bitcoin_amount)); assert_eq!(tlv_stream.0.amount, Some(1000)); assert_eq!(tlv_stream.0.currency, None); #[cfg(not(c_bindings))] - let builder = OfferBuilder::new(pubkey(42)) - .amount(currency_amount.clone()); + let builder = OfferBuilder::new(pubkey(42)).amount(currency_amount.clone()); #[cfg(c_bindings)] let mut builder = OfferBuilder::new(pubkey(42)); #[cfg(c_bindings)] @@ -1519,10 +1577,7 @@ mod tests { #[test] fn builds_offer_with_description() { - let offer = OfferBuilder::new(pubkey(42)) - .description("foo".into()) - .build() - .unwrap(); + let offer = OfferBuilder::new(pubkey(42)).description("foo".into()).build().unwrap(); assert_eq!(offer.description(), Some(PrintableString("foo"))); assert_eq!(offer.as_tlv_stream().0.description, Some(&String::from("foo"))); @@ -1534,10 +1589,7 @@ mod tests { assert_eq!(offer.description(), Some(PrintableString("bar"))); assert_eq!(offer.as_tlv_stream().0.description, Some(&String::from("bar"))); - let offer = OfferBuilder::new(pubkey(42)) - .amount_msats(1000) - .build() - .unwrap(); + let offer = OfferBuilder::new(pubkey(42)).amount_msats(1000).build().unwrap(); assert_eq!(offer.description(), Some(PrintableString(""))); assert_eq!(offer.as_tlv_stream().0.description, Some(&String::from(""))); } @@ -1566,10 +1618,7 @@ mod tests { let past_expiry = Duration::from_secs(0); let now = future_expiry - Duration::from_secs(1_000); - let offer = OfferBuilder::new(pubkey(42)) - .absolute_expiry(future_expiry) - .build() - .unwrap(); + let offer = OfferBuilder::new(pubkey(42)).absolute_expiry(future_expiry).build().unwrap(); #[cfg(feature = "std")] assert!(!offer.is_expired()); assert!(!offer.is_expired_no_std(now)); @@ -1592,18 +1641,20 @@ mod tests { fn builds_offer_with_paths() { let paths = vec![ BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] }, BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] }, - ] + ], ), BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] }, BlindedHop { blinded_node_id: pubkey(46), encrypted_payload: vec![0; 46] }, - ] + ], ), ]; @@ -1622,10 +1673,7 @@ mod tests { #[test] fn builds_offer_with_issuer() { - let offer = OfferBuilder::new(pubkey(42)) - .issuer("foo".into()) - .build() - .unwrap(); + let offer = OfferBuilder::new(pubkey(42)).issuer("foo".into()).build().unwrap(); assert_eq!(offer.issuer(), Some(PrintableString("foo"))); assert_eq!(offer.as_tlv_stream().0.issuer, Some(&String::from("foo"))); @@ -1643,19 +1691,15 @@ mod tests { let one = NonZeroU64::new(1).unwrap(); let ten = NonZeroU64::new(10).unwrap(); - let offer = OfferBuilder::new(pubkey(42)) - .supported_quantity(Quantity::One) - .build() - .unwrap(); + let offer = + OfferBuilder::new(pubkey(42)).supported_quantity(Quantity::One).build().unwrap(); let tlv_stream = offer.as_tlv_stream(); assert!(!offer.expects_quantity()); assert_eq!(offer.supported_quantity(), Quantity::One); assert_eq!(tlv_stream.0.quantity_max, None); - let offer = OfferBuilder::new(pubkey(42)) - .supported_quantity(Quantity::Unbounded) - .build() - .unwrap(); + let offer = + OfferBuilder::new(pubkey(42)).supported_quantity(Quantity::Unbounded).build().unwrap(); let tlv_stream = offer.as_tlv_stream(); assert!(offer.expects_quantity()); assert_eq!(offer.supported_quantity(), Quantity::Unbounded); @@ -1700,7 +1744,8 @@ mod tests { match OfferBuilder::new(pubkey(42)) .features_unchecked(OfferFeatures::unknown()) - .build().unwrap() + .build() + .unwrap() .request_invoice(&expanded_key, nonce, &secp_ctx, payment_id) { Ok(_) => panic!("expected error"), @@ -1750,7 +1795,10 @@ mod tests { match Offer::try_from(encoded_offer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount) + ), } let mut tlv_stream = offer.as_tlv_stream(); @@ -1762,7 +1810,10 @@ mod tests { match Offer::try_from(encoded_offer) { Ok(_) => panic!("expected error"), - Err(e) => assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount)), + Err(e) => assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount) + ), } } @@ -1776,7 +1827,8 @@ mod tests { let offer = OfferBuilder::new(pubkey(42)) .description("foo".to_string()) .amount_msats(1000) - .build().unwrap(); + .build() + .unwrap(); if let Err(e) = offer.to_string().parse::() { panic!("error parsing offer: {:?}", e); } @@ -1790,7 +1842,10 @@ mod tests { match Offer::try_from(encoded_offer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription) + ); }, } } @@ -1799,18 +1854,20 @@ mod tests { fn parses_offer_with_paths() { let offer = OfferBuilder::new(pubkey(42)) .path(BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] }, BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] }, - ] + ], )) .path(BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), - vec![ - BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] }, - BlindedHop { blinded_node_id: pubkey(46), encrypted_payload: vec![0; 46] }, - ] + pubkey(40), + pubkey(41), + vec![ + BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] }, + BlindedHop { blinded_node_id: pubkey(46), encrypted_payload: vec![0; 46] }, + ], )) .build() .unwrap(); @@ -1820,11 +1877,12 @@ mod tests { let offer = OfferBuilder::new(pubkey(42)) .path(BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), - vec![ - BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] }, - BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] }, - ] + pubkey(40), + pubkey(41), + vec![ + BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] }, + BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] }, + ], )) .clear_issuer_signing_pubkey() .build() @@ -1840,25 +1898,24 @@ mod tests { match offer.to_string().parse::() { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaths)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPaths) + ); }, } } #[test] fn parses_offer_with_quantity() { - let offer = OfferBuilder::new(pubkey(42)) - .supported_quantity(Quantity::One) - .build() - .unwrap(); + let offer = + OfferBuilder::new(pubkey(42)).supported_quantity(Quantity::One).build().unwrap(); if let Err(e) = offer.to_string().parse::() { panic!("error parsing offer: {:?}", e); } - let offer = OfferBuilder::new(pubkey(42)) - .supported_quantity(Quantity::Unbounded) - .build() - .unwrap(); + let offer = + OfferBuilder::new(pubkey(42)).supported_quantity(Quantity::Unbounded).build().unwrap(); if let Err(e) = offer.to_string().parse::() { panic!("error parsing offer: {:?}", e); } @@ -1896,7 +1953,12 @@ mod tests { match Offer::try_from(encoded_offer) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingIssuerSigningPubkey)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics( + Bolt12SemanticError::MissingIssuerSigningPubkey + ) + ); }, } } @@ -2073,7 +2135,8 @@ mod bolt12_tests { fn fails_parsing_bech32_encoded_offers() { // Malformed: fields out of order assert_eq!( - "lno1zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszpgz5znzfgdzs".parse::(), + "lno1zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszpgz5znzfgdzs" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)), ); @@ -2086,7 +2149,9 @@ mod bolt12_tests { // Malformed: empty assert_eq!( "lno1".parse::(), - Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingIssuerSigningPubkey)), + Err(Bolt12ParseError::InvalidSemantics( + Bolt12SemanticError::MissingIssuerSigningPubkey + )), ); // Malformed: truncated at type @@ -2115,19 +2180,22 @@ mod bolt12_tests { // Malformed: invalid offer_chains length assert_eq!( - "lno1qgqszzs9g9xyjs69zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz".parse::(), + "lno1qgqszzs9g9xyjs69zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::ShortRead)), ); // Malformed: truncated currency UTF-8 assert_eq!( - "lno1qcqcqzs9g9xyjs69zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz".parse::(), + "lno1qcqcqzs9g9xyjs69zcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::ShortRead)), ); // Malformed: invalid currency UTF-8 assert_eq!( - "lno1qcpgqsg2q4q5cj2rg5tzzqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqg".parse::(), + "lno1qcpgqsg2q4q5cj2rg5tzzqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqg" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::ShortRead)), ); @@ -2145,7 +2213,8 @@ mod bolt12_tests { // Malformed: truncated offer_paths assert_eq!( - "lno1pgz5znzfgdz3qqgpzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz".parse::(), + "lno1pgz5znzfgdz3qqgpzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::ShortRead)), ); @@ -2181,19 +2250,22 @@ mod bolt12_tests { // Malformed: truncated issuer UTF-8 assert_eq!( - "lno1pgz5znzfgdz3yqvqzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz".parse::(), + "lno1pgz5znzfgdz3yqvqzcssyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsz" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)), ); // Malformed: invalid issuer UTF-8 assert_eq!( - "lno1pgz5znzfgdz3yq5qgytzzqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqg".parse::(), + "lno1pgz5znzfgdz3yq5qgytzzqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqg" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)), ); // Malformed: invalid offer_issuer_id assert_eq!( - "lno1pgz5znzfgdz3vggzqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvps".parse::(), + "lno1pgz5znzfgdz3vggzqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvps" + .parse::(), Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)), ); @@ -2231,7 +2303,9 @@ mod bolt12_tests { // Missing offer_issuer_id assert_eq!( "lno1pgx9getnwss8vetrw3hhyuc".parse::(), - Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingIssuerSigningPubkey)), + Err(Bolt12ParseError::InvalidSemantics( + Bolt12SemanticError::MissingIssuerSigningPubkey + )), ); // Second offer_path is empty From 82440469084e8b24b7d359971410c30222d7a10a Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:22 +0100 Subject: [PATCH 12/22] `rustfmt`: Drop `lightning/src/offers/offer.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index 1304602f036..d3a10e35dee 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -39,7 +39,6 @@ lightning/src/ln/shutdown_tests.rs lightning/src/ln/types.rs lightning/src/ln/wire.rs lightning/src/offers/mod.rs -lightning/src/offers/offer.rs lightning/src/offers/parse.rs lightning/src/offers/payer.rs lightning/src/offers/refund.rs From 22b95db7dbad0a653d9a962559f7bb06b2919a34 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:26 +0100 Subject: [PATCH 13/22] `rustfmt`: Run on `lightning/src/offers/parse.rs` --- lightning/src/offers/parse.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/lightning/src/offers/parse.rs b/lightning/src/offers/parse.rs index 6b72c6b1682..75280ea1d2e 100644 --- a/lightning/src/offers/parse.rs +++ b/lightning/src/offers/parse.rs @@ -9,11 +9,11 @@ //! Parsing and formatting for bech32 message encoding. -use bitcoin::secp256k1; use crate::io; use crate::ln::msgs::DecodeError; use crate::util::ser::CursorReadable; use bech32::primitives::decode::CheckedHrpstringError; +use bitcoin::secp256k1; #[allow(unused_imports)] use crate::prelude::*; @@ -25,16 +25,16 @@ pub(super) use sealed::Bech32Encode; pub use sealed::Bech32Encode; mod sealed { - use bech32::{EncodeError, Hrp, NoChecksum, encode_to_fmt}; + use super::Bolt12ParseError; use bech32::primitives::decode::CheckedHrpstring; + use bech32::{encode_to_fmt, EncodeError, Hrp, NoChecksum}; use core::fmt; - use super::Bolt12ParseError; #[allow(unused_imports)] use crate::prelude::*; /// Indicates a message can be encoded using bech32. - pub trait Bech32Encode: AsRef<[u8]> + TryFrom, Error=Bolt12ParseError> { + pub trait Bech32Encode: AsRef<[u8]> + TryFrom, Error = Bolt12ParseError> { /// Human readable part of the message's bech32 encoding. const BECH32_HRP: &'static str; @@ -234,7 +234,7 @@ impl From for Bolt12ParseError { mod bolt12_tests { use super::Bolt12ParseError; use crate::offers::offer::Offer; - use bech32::primitives::decode::{CheckedHrpstringError, UncheckedHrpstringError, CharError}; + use bech32::primitives::decode::{CharError, CheckedHrpstringError, UncheckedHrpstringError}; #[test] fn encodes_offer_as_bech32_without_checksum() { @@ -294,7 +294,12 @@ mod bolt12_tests { let mixed_case_offer = "LnO1PqPs7sJqPgTyZm3qV4UxZmTsD3JjQeR9Wd3hY6TsW35k7mSjZfPy7nZ5YqCnYgRfDeJ82uM5Wf5k2uCkYyPwA3EyT44h6tXtXqUqH7Lz5dJgE4AfGfJn7k4rGrKuAg0jSd5xVxG"; match mixed_case_offer.parse::() { Ok(_) => panic!("Valid offer: {}", mixed_case_offer), - Err(e) => assert_eq!(e, Bolt12ParseError::Bech32(CheckedHrpstringError::Parse(UncheckedHrpstringError::Char(CharError::MixedCase)))), + Err(e) => assert_eq!( + e, + Bolt12ParseError::Bech32(CheckedHrpstringError::Parse( + UncheckedHrpstringError::Char(CharError::MixedCase) + )) + ), } } } @@ -320,7 +325,12 @@ mod tests { let encoded_offer = "lno1pqps7sjqpgtyzm3qv4uxzmtsd3jjqer9wd3hy6tsw35k7msjzfpy7nz5yqcnygrfdej82um5wf5k2uckyypwa3eyt44h6txtxquqh7lz5djge4afgfjn7k4rgrkuag0jsd5xvxo"; match encoded_offer.parse::() { Ok(_) => panic!("Valid offer: {}", encoded_offer), - Err(e) => assert_eq!(e, Bolt12ParseError::Bech32(CheckedHrpstringError::Parse(UncheckedHrpstringError::Char(CharError::InvalidChar('o'))))), + Err(e) => assert_eq!( + e, + Bolt12ParseError::Bech32(CheckedHrpstringError::Parse( + UncheckedHrpstringError::Char(CharError::InvalidChar('o')) + )) + ), } } From 705c15d9fc2eb76db4eefafada05ee0a9faab32d Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:26 +0100 Subject: [PATCH 14/22] `rustfmt`: Drop `lightning/src/offers/parse.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index d3a10e35dee..e4f257df958 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -39,7 +39,6 @@ lightning/src/ln/shutdown_tests.rs lightning/src/ln/types.rs lightning/src/ln/wire.rs lightning/src/offers/mod.rs -lightning/src/offers/parse.rs lightning/src/offers/payer.rs lightning/src/offers/refund.rs lightning/src/offers/signer.rs From 209bf6f91d140c51a83c357fe39a0412c101fd5c Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:30 +0100 Subject: [PATCH 15/22] `rustfmt`: Drop `lightning/src/offers/payer.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index e4f257df958..08fca0da30d 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -39,7 +39,6 @@ lightning/src/ln/shutdown_tests.rs lightning/src/ln/types.rs lightning/src/ln/wire.rs lightning/src/offers/mod.rs -lightning/src/offers/payer.rs lightning/src/offers/refund.rs lightning/src/offers/signer.rs lightning/src/offers/test_utils.rs From 6d9b826b6ee96808c5820a7c6dd21807ca7d32e6 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:35 +0100 Subject: [PATCH 16/22] `rustfmt`: Run on `lightning/src/offers/refund.rs` --- lightning/src/offers/refund.rs | 511 ++++++++++++++++++++------------- 1 file changed, 319 insertions(+), 192 deletions(-) diff --git a/lightning/src/offers/refund.rs b/lightning/src/offers/refund.rs index e562fb3f901..56f3cfa01cf 100644 --- a/lightning/src/offers/refund.rs +++ b/lightning/src/offers/refund.rs @@ -82,38 +82,41 @@ //! [`ChannelManager`]: crate::ln::channelmanager::ChannelManager //! [`ChannelManager::create_refund_builder`]: crate::ln::channelmanager::ChannelManager::create_refund_builder -use bitcoin::constants::ChainHash; -use bitcoin::network::Network; -use bitcoin::secp256k1::{PublicKey, Secp256k1, self}; -use core::hash::{Hash, Hasher}; -use core::ops::Deref; -use core::str::FromStr; -use core::time::Duration; -use crate::sign::EntropySource; -use crate::io; use crate::blinded_path::message::BlindedMessagePath; use crate::blinded_path::payment::BlindedPaymentPath; -use crate::types::payment::PaymentHash; +use crate::io; use crate::ln::channelmanager::PaymentId; -use crate::types::features::InvoiceRequestFeatures; use crate::ln::inbound_payment::{ExpandedKey, IV_LEN}; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; -use crate::offers::invoice_request::{ExperimentalInvoiceRequestTlvStream, ExperimentalInvoiceRequestTlvStreamRef, InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef}; +use crate::offers::invoice_request::{ + ExperimentalInvoiceRequestTlvStream, ExperimentalInvoiceRequestTlvStreamRef, + InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef, +}; use crate::offers::nonce::Nonce; -use crate::offers::offer::{ExperimentalOfferTlvStream, ExperimentalOfferTlvStreamRef, OfferTlvStream, OfferTlvStreamRef}; +use crate::offers::offer::{ + ExperimentalOfferTlvStream, ExperimentalOfferTlvStreamRef, OfferTlvStream, OfferTlvStreamRef, +}; use crate::offers::parse::{Bech32Encode, Bolt12ParseError, Bolt12SemanticError, ParsedMessage}; use crate::offers::payer::{PayerContents, PayerTlvStream, PayerTlvStreamRef}; -use crate::offers::signer::{Metadata, MetadataMaterial, self}; +use crate::offers::signer::{self, Metadata, MetadataMaterial}; +use crate::sign::EntropySource; +use crate::types::features::InvoiceRequestFeatures; +use crate::types::payment::PaymentHash; use crate::util::ser::{CursorReadable, Readable, WithoutLength, Writeable, Writer}; use crate::util::string::PrintableString; +use bitcoin::constants::ChainHash; +use bitcoin::network::Network; +use bitcoin::secp256k1::{self, PublicKey, Secp256k1}; +use core::hash::{Hash, Hasher}; +use core::ops::Deref; +use core::str::FromStr; +use core::time::Duration; #[cfg(not(c_bindings))] -use { - crate::offers::invoice::{DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder}, -}; +use crate::offers::invoice::{DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder}; #[cfg(c_bindings)] -use { - crate::offers::invoice::{InvoiceWithDerivedSigningPubkeyBuilder, InvoiceWithExplicitSigningPubkeyBuilder}, +use crate::offers::invoice::{ + InvoiceWithDerivedSigningPubkeyBuilder, InvoiceWithExplicitSigningPubkeyBuilder, }; #[allow(unused_imports)] @@ -149,42 +152,52 @@ pub struct RefundMaybeWithDerivedMetadataBuilder<'a> { secp_ctx: Option<&'a Secp256k1>, } -macro_rules! refund_explicit_metadata_builder_methods { () => { - /// Creates a new builder for a refund using the `signing_pubkey` for the public node id to send - /// to if no [`Refund::paths`] are set. Otherwise, `signing_pubkey` may be a transient pubkey. - /// - /// Additionally, sets the required (empty) [`Refund::description`], [`Refund::payer_metadata`], - /// and [`Refund::amount_msats`]. - /// - /// # Note - /// - /// If constructing a [`Refund`] for use with a [`ChannelManager`], use - /// [`ChannelManager::create_refund_builder`] instead of [`RefundBuilder::new`]. - /// - /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager - /// [`ChannelManager::create_refund_builder`]: crate::ln::channelmanager::ChannelManager::create_refund_builder - pub fn new( - metadata: Vec, signing_pubkey: PublicKey, amount_msats: u64 - ) -> Result { - if amount_msats > MAX_VALUE_MSAT { - return Err(Bolt12SemanticError::InvalidAmount); - } +macro_rules! refund_explicit_metadata_builder_methods { + () => { + /// Creates a new builder for a refund using the `signing_pubkey` for the public node id to send + /// to if no [`Refund::paths`] are set. Otherwise, `signing_pubkey` may be a transient pubkey. + /// + /// Additionally, sets the required (empty) [`Refund::description`], [`Refund::payer_metadata`], + /// and [`Refund::amount_msats`]. + /// + /// # Note + /// + /// If constructing a [`Refund`] for use with a [`ChannelManager`], use + /// [`ChannelManager::create_refund_builder`] instead of [`RefundBuilder::new`]. + /// + /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager + /// [`ChannelManager::create_refund_builder`]: crate::ln::channelmanager::ChannelManager::create_refund_builder + pub fn new( + metadata: Vec, signing_pubkey: PublicKey, amount_msats: u64, + ) -> Result { + if amount_msats > MAX_VALUE_MSAT { + return Err(Bolt12SemanticError::InvalidAmount); + } - let metadata = Metadata::Bytes(metadata); - Ok(Self { - refund: RefundContents { - payer: PayerContents(metadata), description: String::new(), absolute_expiry: None, - issuer: None, chain: None, amount_msats, features: InvoiceRequestFeatures::empty(), - quantity: None, payer_signing_pubkey: signing_pubkey, payer_note: None, paths: None, - #[cfg(test)] - experimental_foo: None, - #[cfg(test)] - experimental_bar: None, - }, - secp_ctx: None, - }) - } -} } + let metadata = Metadata::Bytes(metadata); + Ok(Self { + refund: RefundContents { + payer: PayerContents(metadata), + description: String::new(), + absolute_expiry: None, + issuer: None, + chain: None, + amount_msats, + features: InvoiceRequestFeatures::empty(), + quantity: None, + payer_signing_pubkey: signing_pubkey, + payer_note: None, + paths: None, + #[cfg(test)] + experimental_foo: None, + #[cfg(test)] + experimental_bar: None, + }, + secp_ctx: None, + }) + } + }; +} macro_rules! refund_builder_methods { ( $self: ident, $self_type: ty, $return_type: ty, $return_value: expr, $secp_context: ty $(, $self_mut: tt)? @@ -406,8 +419,7 @@ impl<'a> RefundMaybeWithDerivedMetadataBuilder<'a> { } #[cfg(c_bindings)] -impl<'a> From> -for RefundMaybeWithDerivedMetadataBuilder<'a> { +impl<'a> From> for RefundMaybeWithDerivedMetadataBuilder<'a> { fn from(builder: RefundBuilder<'a, secp256k1::All>) -> Self { let RefundBuilder { refund, secp_ctx } = builder; @@ -416,8 +428,7 @@ for RefundMaybeWithDerivedMetadataBuilder<'a> { } #[cfg(c_bindings)] -impl<'a> From> -for RefundBuilder<'a, secp256k1::All> { +impl<'a> From> for RefundBuilder<'a, secp256k1::All> { fn from(builder: RefundMaybeWithDerivedMetadataBuilder<'a>) -> Self { let RefundMaybeWithDerivedMetadataBuilder { refund, secp_ctx } = builder; @@ -762,9 +773,7 @@ impl RefundContents { } pub(super) fn as_tlv_stream(&self) -> RefundTlvStreamRef { - let payer = PayerTlvStreamRef { - metadata: self.payer.0.as_bytes(), - }; + let payer = PayerTlvStreamRef { metadata: self.payer.0.as_bytes() }; let offer = OfferTlvStreamRef { chains: None, @@ -781,8 +790,11 @@ impl RefundContents { }; let features = { - if self.features == InvoiceRequestFeatures::empty() { None } - else { Some(&self.features) } + if self.features == InvoiceRequestFeatures::empty() { + None + } else { + Some(&self.features) + } }; let invoice_request = InvoiceRequestTlvStreamRef { @@ -830,7 +842,10 @@ impl Writeable for RefundContents { } type RefundTlvStream = ( - PayerTlvStream, OfferTlvStream, InvoiceRequestTlvStream, ExperimentalOfferTlvStream, + PayerTlvStream, + OfferTlvStream, + InvoiceRequestTlvStream, + ExperimentalOfferTlvStream, ExperimentalInvoiceRequestTlvStream, ); @@ -885,12 +900,26 @@ impl TryFrom for RefundContents { let ( PayerTlvStream { metadata: payer_metadata }, OfferTlvStream { - chains, metadata, currency, amount: offer_amount, description, - features: offer_features, absolute_expiry, paths: offer_paths, issuer, quantity_max, + chains, + metadata, + currency, + amount: offer_amount, + description, + features: offer_features, + absolute_expiry, + paths: offer_paths, + issuer, + quantity_max, issuer_id, }, InvoiceRequestTlvStream { - chain, amount, features, quantity, payer_id, payer_note, paths, + chain, + amount, + features, + quantity, + payer_id, + payer_note, + paths, offer_from_hrn, }, ExperimentalOfferTlvStream { @@ -964,8 +993,17 @@ impl TryFrom for RefundContents { }; Ok(RefundContents { - payer, description, absolute_expiry, issuer, chain, amount_msats, features, quantity, - payer_signing_pubkey, payer_note, paths, + payer, + description, + absolute_expiry, + issuer, + chain, + amount_msats, + features, + quantity, + payer_signing_pubkey, + payer_note, + paths, #[cfg(test)] experimental_foo, #[cfg(test)] @@ -982,15 +1020,11 @@ impl core::fmt::Display for Refund { #[cfg(test)] mod tests { - use super::{Refund, RefundTlvStreamRef}; #[cfg(not(c_bindings))] - use { - super::RefundBuilder, - }; + use super::RefundBuilder; #[cfg(c_bindings)] - use { - super::RefundMaybeWithDerivedMetadataBuilder as RefundBuilder, - }; + use super::RefundMaybeWithDerivedMetadataBuilder as RefundBuilder; + use super::{Refund, RefundTlvStreamRef}; use bitcoin::constants::ChainHash; use bitcoin::network::Network; @@ -998,21 +1032,24 @@ mod tests { use core::time::Duration; - use crate::blinded_path::BlindedHop; use crate::blinded_path::message::BlindedMessagePath; + use crate::blinded_path::BlindedHop; use crate::ln::channelmanager::PaymentId; - use crate::types::features::{InvoiceRequestFeatures, OfferFeatures}; use crate::ln::inbound_payment::ExpandedKey; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; - use crate::offers::invoice_request::{EXPERIMENTAL_INVOICE_REQUEST_TYPES, ExperimentalInvoiceRequestTlvStreamRef, INVOICE_REQUEST_TYPES, InvoiceRequestTlvStreamRef}; + use crate::offers::invoice_request::{ + ExperimentalInvoiceRequestTlvStreamRef, InvoiceRequestTlvStreamRef, + EXPERIMENTAL_INVOICE_REQUEST_TYPES, INVOICE_REQUEST_TYPES, + }; use crate::offers::nonce::Nonce; use crate::offers::offer::{ExperimentalOfferTlvStreamRef, OfferTlvStreamRef}; use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError}; use crate::offers::payer::PayerTlvStreamRef; use crate::offers::test_utils::*; + use crate::prelude::*; + use crate::types::features::{InvoiceRequestFeatures, OfferFeatures}; use crate::util::ser::{BigSize, Writeable}; use crate::util::string::PrintableString; - use crate::prelude::*; trait ToBytes { fn to_bytes(&self) -> Vec; @@ -1028,8 +1065,8 @@ mod tests { #[test] fn builds_refund_with_defaults() { - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = + RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap().build().unwrap(); let mut buffer = Vec::new(); refund.write(&mut buffer).unwrap(); @@ -1075,12 +1112,8 @@ mod tests { paths: None, offer_from_hrn: None, }, - ExperimentalOfferTlvStreamRef { - experimental_foo: None, - }, - ExperimentalInvoiceRequestTlvStreamRef { - experimental_bar: None, - }, + ExperimentalOfferTlvStreamRef { experimental_foo: None }, + ExperimentalInvoiceRequestTlvStreamRef { experimental_bar: None }, ), ); @@ -1106,12 +1139,19 @@ mod tests { let secp_ctx = Secp256k1::new(); let payment_id = PaymentId([1; 32]); - let refund = RefundBuilder - ::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx, 1000, payment_id) - .unwrap() - .experimental_foo(42) - .experimental_bar(42) - .build().unwrap(); + let refund = RefundBuilder::deriving_signing_pubkey( + node_id, + &expanded_key, + nonce, + &secp_ctx, + 1000, + payment_id, + ) + .unwrap() + .experimental_foo(42) + .experimental_bar(42) + .build() + .unwrap(); assert_eq!(refund.payer_signing_pubkey(), node_id); // Fails verification with altered fields @@ -1119,15 +1159,17 @@ mod tests { .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) .unwrap() .experimental_baz(42) - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); match invoice.verify_using_metadata(&expanded_key, &secp_ctx) { Ok(payment_id) => assert_eq!(payment_id, PaymentId([1; 32])), Err(()) => panic!("verification failed"), } - assert!( - invoice.verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx).is_err() - ); + assert!(invoice + .verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx) + .is_err()); let mut tlv_stream = refund.as_tlv_stream(); tlv_stream.2.amount = Some(2000); @@ -1135,11 +1177,14 @@ mod tests { let mut encoded_refund = Vec::new(); tlv_stream.write(&mut encoded_refund).unwrap(); - let invoice = Refund::try_from(encoded_refund).unwrap() + let invoice = Refund::try_from(encoded_refund) + .unwrap() .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); assert!(invoice.verify_using_metadata(&expanded_key, &secp_ctx).is_err()); // Fails verification with altered metadata @@ -1150,11 +1195,14 @@ mod tests { let mut encoded_refund = Vec::new(); tlv_stream.write(&mut encoded_refund).unwrap(); - let invoice = Refund::try_from(encoded_refund).unwrap() + let invoice = Refund::try_from(encoded_refund) + .unwrap() .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); assert!(invoice.verify_using_metadata(&expanded_key, &secp_ctx).is_err()); } @@ -1168,32 +1216,42 @@ mod tests { let payment_id = PaymentId([1; 32]); let blinded_path = BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] }, BlindedHop { blinded_node_id: node_id, encrypted_payload: vec![0; 44] }, - ] + ], ); - let refund = RefundBuilder - ::deriving_signing_pubkey(node_id, &expanded_key, nonce, &secp_ctx, 1000, payment_id) - .unwrap() - .path(blinded_path) - .experimental_foo(42) - .experimental_bar(42) - .build().unwrap(); + let refund = RefundBuilder::deriving_signing_pubkey( + node_id, + &expanded_key, + nonce, + &secp_ctx, + 1000, + payment_id, + ) + .unwrap() + .path(blinded_path) + .experimental_foo(42) + .experimental_bar(42) + .build() + .unwrap(); assert_ne!(refund.payer_signing_pubkey(), node_id); let invoice = refund .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) .unwrap() .experimental_baz(42) - .build().unwrap() - .sign(recipient_sign).unwrap(); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); assert!(invoice.verify_using_metadata(&expanded_key, &secp_ctx).is_err()); - assert!( - invoice.verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx).is_ok() - ); + assert!(invoice + .verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx) + .is_ok()); // Fails verification with altered fields let mut tlv_stream = refund.as_tlv_stream(); @@ -1202,14 +1260,17 @@ mod tests { let mut encoded_refund = Vec::new(); tlv_stream.write(&mut encoded_refund).unwrap(); - let invoice = Refund::try_from(encoded_refund).unwrap() + let invoice = Refund::try_from(encoded_refund) + .unwrap() .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); - assert!( - invoice.verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx).is_err() - ); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); + assert!(invoice + .verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx) + .is_err()); // Fails verification with altered payer_id let mut tlv_stream = refund.as_tlv_stream(); @@ -1219,14 +1280,17 @@ mod tests { let mut encoded_refund = Vec::new(); tlv_stream.write(&mut encoded_refund).unwrap(); - let invoice = Refund::try_from(encoded_refund).unwrap() + let invoice = Refund::try_from(encoded_refund) + .unwrap() .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) .unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); - assert!( - invoice.verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx).is_err() - ); + .build() + .unwrap() + .sign(recipient_sign) + .unwrap(); + assert!(invoice + .verify_using_payer_data(payment_id, nonce, &expanded_key, &secp_ctx) + .is_err()); } #[test] @@ -1235,7 +1299,8 @@ mod tests { let past_expiry = Duration::from_secs(0); let now = future_expiry - Duration::from_secs(1_000); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .absolute_expiry(future_expiry) .build() .unwrap(); @@ -1246,7 +1311,8 @@ mod tests { assert_eq!(refund.absolute_expiry(), Some(future_expiry)); assert_eq!(tlv_stream.absolute_expiry, Some(future_expiry.as_secs())); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .absolute_expiry(future_expiry) .absolute_expiry(past_expiry) .build() @@ -1263,22 +1329,25 @@ mod tests { fn builds_refund_with_paths() { let paths = vec![ BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] }, BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] }, - ] + ], ), BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] }, BlindedHop { blinded_node_id: pubkey(46), encrypted_payload: vec![0; 46] }, - ] + ], ), ]; - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .path(paths[0].clone()) .path(paths[1].clone()) .build() @@ -1293,7 +1362,8 @@ mod tests { #[test] fn builds_refund_with_issuer() { - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .issuer("bar".into()) .build() .unwrap(); @@ -1301,7 +1371,8 @@ mod tests { assert_eq!(refund.issuer(), Some(PrintableString("bar"))); assert_eq!(tlv_stream.issuer, Some(&String::from("bar"))); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .issuer("bar".into()) .issuer("baz".into()) .build() @@ -1316,24 +1387,30 @@ mod tests { let mainnet = ChainHash::using_genesis_block(Network::Bitcoin); let testnet = ChainHash::using_genesis_block(Network::Testnet); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .chain(Network::Bitcoin) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream, _, _) = refund.as_tlv_stream(); assert_eq!(refund.chain(), mainnet); assert_eq!(tlv_stream.chain, None); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .chain(Network::Testnet) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream, _, _) = refund.as_tlv_stream(); assert_eq!(refund.chain(), testnet); assert_eq!(tlv_stream.chain, Some(&testnet)); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .chain(Network::Regtest) .chain(Network::Testnet) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream, _, _) = refund.as_tlv_stream(); assert_eq!(refund.chain(), testnet); assert_eq!(tlv_stream.chain, Some(&testnet)); @@ -1341,17 +1418,21 @@ mod tests { #[test] fn builds_refund_with_quantity() { - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .quantity(10) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream, _, _) = refund.as_tlv_stream(); assert_eq!(refund.quantity(), Some(10)); assert_eq!(tlv_stream.quantity, Some(10)); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .quantity(10) .quantity(1) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream, _, _) = refund.as_tlv_stream(); assert_eq!(refund.quantity(), Some(1)); assert_eq!(tlv_stream.quantity, Some(1)); @@ -1359,17 +1440,21 @@ mod tests { #[test] fn builds_refund_with_payer_note() { - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .payer_note("bar".into()) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream, _, _) = refund.as_tlv_stream(); assert_eq!(refund.payer_note(), Some(PrintableString("bar"))); assert_eq!(tlv_stream.payer_note, Some(&String::from("bar"))); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .payer_note("bar".into()) .payer_note("baz".into()) - .build().unwrap(); + .build() + .unwrap(); let (_, _, tlv_stream, _, _) = refund.as_tlv_stream(); assert_eq!(refund.payer_note(), Some(PrintableString("baz"))); assert_eq!(tlv_stream.payer_note, Some(&String::from("baz"))); @@ -1377,9 +1462,11 @@ mod tests { #[test] fn fails_responding_with_unknown_required_features() { - match RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + match RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .features_unchecked(InvoiceRequestFeatures::unknown()) - .build().unwrap() + .build() + .unwrap() .respond_with_no_std(payment_paths(), payment_hash(), recipient_pubkey(), now()) { Ok(_) => panic!("expected error"), @@ -1389,8 +1476,8 @@ mod tests { #[test] fn parses_refund_with_metadata() { - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = + RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap().build().unwrap(); if let Err(e) = refund.to_string().parse::() { panic!("error parsing refund: {:?}", e); } @@ -1401,15 +1488,18 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerMetadata)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerMetadata) + ); }, } } #[test] fn parses_refund_with_description() { - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = + RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap().build().unwrap(); if let Err(e) = refund.to_string().parse::() { panic!("error parsing refund: {:?}", e); } @@ -1420,15 +1510,18 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingDescription) + ); }, } } #[test] fn parses_refund_with_amount() { - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = + RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap().build().unwrap(); if let Err(e) = refund.to_string().parse::() { panic!("error parsing refund: {:?}", e); } @@ -1439,7 +1532,10 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingAmount) + ); }, } @@ -1449,15 +1545,18 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::InvalidAmount) + ); }, } } #[test] fn parses_refund_with_payer_id() { - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = + RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap().build().unwrap(); if let Err(e) = refund.to_string().parse::() { panic!("error parsing refund: {:?}", e); } @@ -1468,7 +1567,12 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingPayerSigningPubkey)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics( + Bolt12SemanticError::MissingPayerSigningPubkey + ) + ); }, } } @@ -1478,22 +1582,25 @@ mod tests { let past_expiry = Duration::from_secs(0); let paths = vec![ BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] }, BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] }, - ] + ], ), BlindedMessagePath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] }, BlindedHop { blinded_node_id: pubkey(46), encrypted_payload: vec![0; 46] }, - ] + ], ), ]; - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() + let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000) + .unwrap() .absolute_expiry(past_expiry) .issuer("bar".into()) .path(paths[0].clone()) @@ -1522,8 +1629,8 @@ mod tests { #[test] fn fails_parsing_refund_with_unexpected_fields() { - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = + RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap().build().unwrap(); if let Err(e) = refund.to_string().parse::() { panic!("error parsing refund: {:?}", e); } @@ -1535,7 +1642,10 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedMetadata)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedMetadata) + ); }, } @@ -1546,7 +1656,10 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedChain)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedChain) + ); }, } @@ -1557,7 +1670,10 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedAmount)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedAmount) + ); }, } @@ -1568,7 +1684,10 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedFeatures)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedFeatures) + ); }, } @@ -1578,7 +1697,10 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedQuantity)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedQuantity) + ); }, } @@ -1589,7 +1711,12 @@ mod tests { match Refund::try_from(tlv_stream.to_bytes()) { Ok(_) => panic!("expected error"), Err(e) => { - assert_eq!(e, Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::UnexpectedIssuerSigningPubkey)); + assert_eq!( + e, + Bolt12ParseError::InvalidSemantics( + Bolt12SemanticError::UnexpectedIssuerSigningPubkey + ) + ); }, } } @@ -1599,8 +1726,8 @@ mod tests { const UNKNOWN_ODD_TYPE: u64 = INVOICE_REQUEST_TYPES.end - 1; assert!(UNKNOWN_ODD_TYPE % 2 == 1); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = + RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap().build().unwrap(); let mut encoded_refund = Vec::new(); refund.write(&mut encoded_refund).unwrap(); @@ -1616,8 +1743,8 @@ mod tests { const UNKNOWN_EVEN_TYPE: u64 = INVOICE_REQUEST_TYPES.end - 2; assert!(UNKNOWN_EVEN_TYPE % 2 == 0); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = + RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap().build().unwrap(); let mut encoded_refund = Vec::new(); refund.write(&mut encoded_refund).unwrap(); @@ -1636,8 +1763,8 @@ mod tests { const UNKNOWN_ODD_TYPE: u64 = EXPERIMENTAL_INVOICE_REQUEST_TYPES.start + 1; assert!(UNKNOWN_ODD_TYPE % 2 == 1); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = + RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap().build().unwrap(); let mut encoded_refund = Vec::new(); refund.write(&mut encoded_refund).unwrap(); @@ -1653,8 +1780,8 @@ mod tests { const UNKNOWN_EVEN_TYPE: u64 = EXPERIMENTAL_INVOICE_REQUEST_TYPES.start; assert!(UNKNOWN_EVEN_TYPE % 2 == 0); - let refund = RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap() - .build().unwrap(); + let refund = + RefundBuilder::new(vec![1; 32], payer_pubkey(), 1000).unwrap().build().unwrap(); let mut encoded_refund = Vec::new(); refund.write(&mut encoded_refund).unwrap(); @@ -1672,8 +1799,8 @@ mod tests { fn fails_parsing_refund_with_out_of_range_tlv_records() { let secp_ctx = Secp256k1::new(); let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); - let refund = RefundBuilder::new(vec![1; 32], keys.public_key(), 1000).unwrap() - .build().unwrap(); + let refund = + RefundBuilder::new(vec![1; 32], keys.public_key(), 1000).unwrap().build().unwrap(); let mut encoded_refund = Vec::new(); refund.write(&mut encoded_refund).unwrap(); From 25ef4aa99cf5256f09aa8f33a905371f2653ee28 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:35 +0100 Subject: [PATCH 17/22] `rustfmt`: Drop `lightning/src/offers/refund.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index 08fca0da30d..561041220c8 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -39,7 +39,6 @@ lightning/src/ln/shutdown_tests.rs lightning/src/ln/types.rs lightning/src/ln/wire.rs lightning/src/offers/mod.rs -lightning/src/offers/refund.rs lightning/src/offers/signer.rs lightning/src/offers/test_utils.rs lightning/src/routing/mod.rs From a129e0ba63a44403a32cd6875b1c06223cb87011 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:40 +0100 Subject: [PATCH 18/22] `rustfmt`: Run on `lightning/src/offers/signer.rs` --- lightning/src/offers/signer.rs | 137 ++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 45 deletions(-) diff --git a/lightning/src/offers/signer.rs b/lightning/src/offers/signer.rs index 93ff4ecea3b..84540fc13e0 100644 --- a/lightning/src/offers/signer.rs +++ b/lightning/src/offers/signer.rs @@ -9,19 +9,19 @@ //! Utilities for signing offer messages and verifying metadata. -use bitcoin::hashes::{Hash, HashEngine}; -use bitcoin::hashes::cmp::fixed_time_eq; -use bitcoin::hashes::hmac::{Hmac, HmacEngine}; -use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey, self}; -use types::payment::PaymentHash; -use core::fmt; use crate::blinded_path::payment::UnauthenticatedReceiveTlvs; use crate::ln::channelmanager::PaymentId; use crate::ln::inbound_payment::{ExpandedKey, IV_LEN}; use crate::offers::merkle::TlvRecord; use crate::offers::nonce::Nonce; use crate::util::ser::Writeable; +use bitcoin::hashes::cmp::fixed_time_eq; +use bitcoin::hashes::hmac::{Hmac, HmacEngine}; +use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::{Hash, HashEngine}; +use bitcoin::secp256k1::{self, Keypair, PublicKey, Secp256k1, SecretKey}; +use core::fmt; +use types::payment::PaymentHash; use crate::prelude::*; @@ -99,15 +99,24 @@ impl Metadata { pub fn as_bytes(&self) -> Option<&Vec> { match self { Metadata::Bytes(bytes) => Some(bytes), - _ => { debug_assert!(false); None }, + _ => { + debug_assert!(false); + None + }, } } pub fn has_derivation_material(&self) -> bool { match self { Metadata::Bytes(_) => false, - Metadata::RecipientData(_) => { debug_assert!(false); false }, - Metadata::PayerData(_) => { debug_assert!(false); false }, + Metadata::RecipientData(_) => { + debug_assert!(false); + false + }, + Metadata::PayerData(_) => { + debug_assert!(false); + false + }, Metadata::Derived(_) => true, Metadata::DerivedSigningPubkey(_) => true, } @@ -151,20 +160,32 @@ impl Metadata { pub fn without_keys(self) -> Self { match self { Metadata::Bytes(_) => self, - Metadata::RecipientData(_) => { debug_assert!(false); self }, - Metadata::PayerData(_) => { debug_assert!(false); self }, + Metadata::RecipientData(_) => { + debug_assert!(false); + self + }, + Metadata::PayerData(_) => { + debug_assert!(false); + self + }, Metadata::Derived(_) => self, Metadata::DerivedSigningPubkey(material) => Metadata::Derived(material), } } pub fn derive_from( - self, iv_bytes: &[u8; IV_LEN], tlv_stream: W, secp_ctx: Option<&Secp256k1> + self, iv_bytes: &[u8; IV_LEN], tlv_stream: W, secp_ctx: Option<&Secp256k1>, ) -> (Self, Option) { match self { Metadata::Bytes(_) => (self, None), - Metadata::RecipientData(_) => { debug_assert!(false); (self, None) }, - Metadata::PayerData(_) => { debug_assert!(false); (self, None) }, + Metadata::RecipientData(_) => { + debug_assert!(false); + (self, None) + }, + Metadata::PayerData(_) => { + debug_assert!(false); + (self, None) + }, Metadata::Derived(metadata_material) => { (Metadata::Bytes(metadata_material.derive_metadata(iv_bytes, tlv_stream)), None) }, @@ -190,8 +211,14 @@ impl AsRef<[u8]> for Metadata { Metadata::Bytes(bytes) => &bytes, Metadata::RecipientData(nonce) => &nonce.0, Metadata::PayerData(bytes) => bytes.as_slice(), - Metadata::Derived(_) => { debug_assert!(false); &[] }, - Metadata::DerivedSigningPubkey(_) => { debug_assert!(false); &[] }, + Metadata::Derived(_) => { + debug_assert!(false); + &[] + }, + Metadata::DerivedSigningPubkey(_) => { + debug_assert!(false); + &[] + }, } } } @@ -212,10 +239,12 @@ impl fmt::Debug for Metadata { impl PartialEq for Metadata { fn eq(&self, other: &Self) -> bool { match self { - Metadata::Bytes(bytes) => if let Metadata::Bytes(other_bytes) = other { - bytes == other_bytes - } else { - false + Metadata::Bytes(bytes) => { + if let Metadata::Bytes(other_bytes) = other { + bytes == other_bytes + } else { + false + } }, Metadata::RecipientData(_) => false, Metadata::PayerData(_) => false, @@ -237,15 +266,10 @@ pub(super) struct MetadataMaterial { impl MetadataMaterial { pub fn new(nonce: Nonce, expanded_key: &ExpandedKey, payment_id: Option) -> Self { // Encrypt payment_id - let encrypted_payment_id = payment_id.map(|payment_id| { - expanded_key.crypt_for_offer(payment_id.0, nonce) - }); - - Self { - nonce, - hmac: expanded_key.hmac_for_offer(), - encrypted_payment_id, - } + let encrypted_payment_id = + payment_id.map(|payment_id| expanded_key.crypt_for_offer(payment_id.0, nonce)); + + Self { nonce, hmac: expanded_key.hmac_for_offer(), encrypted_payment_id } } fn derive_metadata(mut self, iv_bytes: &[u8; IV_LEN], tlv_stream: W) -> Vec { @@ -263,7 +287,7 @@ impl MetadataMaterial { } fn derive_metadata_and_keys( - mut self, iv_bytes: &[u8; IV_LEN], tlv_stream: W, secp_ctx: &Secp256k1 + mut self, iv_bytes: &[u8; IV_LEN], tlv_stream: W, secp_ctx: &Secp256k1, ) -> (Vec, Keypair) { self.hmac.input(iv_bytes); self.hmac.input(&self.nonce.0); @@ -315,7 +339,7 @@ pub(super) fn derive_keys(nonce: Nonce, expanded_key: &ExpandedKey) -> Keypair { pub(super) fn verify_payer_metadata<'a, T: secp256k1::Signing>( metadata: &[u8], expanded_key: &ExpandedKey, iv_bytes: &[u8; IV_LEN], signing_pubkey: PublicKey, tlv_stream: impl core::iter::Iterator>, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result { if metadata.len() < PaymentId::LENGTH { return Err(()); @@ -324,14 +348,16 @@ pub(super) fn verify_payer_metadata<'a, T: secp256k1::Signing>( let mut encrypted_payment_id = [0u8; PaymentId::LENGTH]; encrypted_payment_id.copy_from_slice(&metadata[..PaymentId::LENGTH]); - let mut hmac = hmac_for_message( - &metadata[PaymentId::LENGTH..], expanded_key, iv_bytes, tlv_stream - )?; + let mut hmac = + hmac_for_message(&metadata[PaymentId::LENGTH..], expanded_key, iv_bytes, tlv_stream)?; hmac.input(WITH_ENCRYPTED_PAYMENT_ID_HMAC_INPUT); hmac.input(&encrypted_payment_id); verify_metadata( - &metadata[PaymentId::LENGTH..], Hmac::from_engine(hmac), signing_pubkey, secp_ctx + &metadata[PaymentId::LENGTH..], + Hmac::from_engine(hmac), + signing_pubkey, + secp_ctx, )?; let nonce = Nonce::try_from(&metadata[PaymentId::LENGTH..][..Nonce::LENGTH]).unwrap(); @@ -351,7 +377,7 @@ pub(super) fn verify_payer_metadata<'a, T: secp256k1::Signing>( pub(super) fn verify_recipient_metadata<'a, T: secp256k1::Signing>( metadata: &[u8], expanded_key: &ExpandedKey, iv_bytes: &[u8; IV_LEN], signing_pubkey: PublicKey, tlv_stream: impl core::iter::Iterator>, - secp_ctx: &Secp256k1 + secp_ctx: &Secp256k1, ) -> Result, ()> { let mut hmac = hmac_for_message(metadata, expanded_key, iv_bytes, tlv_stream)?; hmac.input(WITHOUT_ENCRYPTED_PAYMENT_ID_HMAC_INPUT); @@ -360,11 +386,12 @@ pub(super) fn verify_recipient_metadata<'a, T: secp256k1::Signing>( } fn verify_metadata( - metadata: &[u8], hmac: Hmac, signing_pubkey: PublicKey, secp_ctx: &Secp256k1 + metadata: &[u8], hmac: Hmac, signing_pubkey: PublicKey, secp_ctx: &Secp256k1, ) -> Result, ()> { if metadata.len() == Nonce::LENGTH { let derived_keys = Keypair::from_secret_key( - secp_ctx, &SecretKey::from_slice(hmac.as_byte_array()).unwrap() + secp_ctx, + &SecretKey::from_slice(hmac.as_byte_array()).unwrap(), ); if fixed_time_eq(&signing_pubkey.serialize(), &derived_keys.public_key().serialize()) { Ok(Some(derived_keys)) @@ -384,7 +411,7 @@ fn verify_metadata( fn hmac_for_message<'a>( metadata: &[u8], expanded_key: &ExpandedKey, iv_bytes: &[u8; IV_LEN], - tlv_stream: impl core::iter::Iterator> + tlv_stream: impl core::iter::Iterator>, ) -> Result, ()> { if metadata.len() < Nonce::LENGTH { return Err(()); @@ -420,7 +447,11 @@ pub(crate) fn hmac_for_offer_payment_id( pub(crate) fn verify_offer_payment_id( payment_id: PaymentId, hmac: Hmac, nonce: Nonce, expanded_key: &ExpandedKey, ) -> Result<(), ()> { - if hmac_for_offer_payment_id(payment_id, nonce, expanded_key) == hmac { Ok(()) } else { Err(()) } + if hmac_for_offer_payment_id(payment_id, nonce, expanded_key) == hmac { + Ok(()) + } else { + Err(()) + } } pub(crate) fn hmac_for_payment_hash( @@ -439,7 +470,11 @@ pub(crate) fn hmac_for_payment_hash( pub(crate) fn verify_payment_hash( payment_hash: PaymentHash, hmac: Hmac, nonce: Nonce, expanded_key: &ExpandedKey, ) -> Result<(), ()> { - if hmac_for_payment_hash(payment_hash, nonce, expanded_key) == hmac { Ok(()) } else { Err(()) } + if hmac_for_payment_hash(payment_hash, nonce, expanded_key) == hmac { + Ok(()) + } else { + Err(()) + } } #[cfg(async_payments)] @@ -453,7 +488,11 @@ pub(crate) fn hmac_for_async_payment_id( pub(crate) fn verify_async_payment_id( payment_id: PaymentId, hmac: Hmac, nonce: Nonce, expanded_key: &ExpandedKey, ) -> Result<(), ()> { - if hmac_for_async_payment_id(payment_id, nonce, expanded_key) == hmac { Ok(()) } else { Err(()) } + if hmac_for_async_payment_id(payment_id, nonce, expanded_key) == hmac { + Ok(()) + } else { + Err(()) + } } fn hmac_for_payment_id( @@ -486,7 +525,11 @@ pub(crate) fn verify_payment_tlvs( receive_tlvs: &UnauthenticatedReceiveTlvs, hmac: Hmac, nonce: Nonce, expanded_key: &ExpandedKey, ) -> Result<(), ()> { - if hmac_for_payment_tlvs(receive_tlvs, nonce, expanded_key) == hmac { Ok(()) } else { Err(()) } + if hmac_for_payment_tlvs(receive_tlvs, nonce, expanded_key) == hmac { + Ok(()) + } else { + Err(()) + } } #[cfg(async_payments)] @@ -506,5 +549,9 @@ pub(crate) fn hmac_for_held_htlc_available_context( pub(crate) fn verify_held_htlc_available_context( nonce: Nonce, hmac: Hmac, expanded_key: &ExpandedKey, ) -> Result<(), ()> { - if hmac_for_held_htlc_available_context(nonce, expanded_key) == hmac { Ok(()) } else { Err(()) } + if hmac_for_held_htlc_available_context(nonce, expanded_key) == hmac { + Ok(()) + } else { + Err(()) + } } From d96c4f7b66ca2cceea631295f4c2301f41a847bb Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:40 +0100 Subject: [PATCH 19/22] `rustfmt`: Drop `lightning/src/offers/signer.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index 561041220c8..a54e5ddce56 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -39,7 +39,6 @@ lightning/src/ln/shutdown_tests.rs lightning/src/ln/types.rs lightning/src/ln/wire.rs lightning/src/offers/mod.rs -lightning/src/offers/signer.rs lightning/src/offers/test_utils.rs lightning/src/routing/mod.rs lightning/src/routing/router.rs From ea1dd92b24927290ecc557d8c78f050f778b30e2 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:49 +0100 Subject: [PATCH 20/22] `rustfmt`: Run on `lightning/src/offers/test_utils.rs` --- lightning/src/offers/test_utils.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lightning/src/offers/test_utils.rs b/lightning/src/offers/test_utils.rs index 3c6016e20c6..4b088705a46 100644 --- a/lightning/src/offers/test_utils.rs +++ b/lightning/src/offers/test_utils.rs @@ -9,16 +9,16 @@ //! Utilities for testing BOLT 12 Offers interfaces -use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey}; use bitcoin::secp256k1::schnorr::Signature; +use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey}; -use core::time::Duration; -use crate::blinded_path::BlindedHop; use crate::blinded_path::payment::{BlindedPayInfo, BlindedPaymentPath}; +use crate::blinded_path::BlindedHop; +use crate::offers::merkle::TaggedHash; use crate::sign::EntropySource; -use crate::types::payment::PaymentHash; use crate::types::features::BlindedHopFeatures; -use crate::offers::merkle::TaggedHash; +use crate::types::payment::PaymentHash; +use core::time::Duration; #[allow(unused_imports)] use crate::prelude::*; @@ -69,7 +69,8 @@ pub(super) fn privkey(byte: u8) -> SecretKey { pub(crate) fn payment_paths() -> Vec { vec![ BlindedPaymentPath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] }, BlindedHop { blinded_node_id: pubkey(44), encrypted_payload: vec![0; 44] }, @@ -84,7 +85,8 @@ pub(crate) fn payment_paths() -> Vec { }, ), BlindedPaymentPath::from_raw( - pubkey(40), pubkey(41), + pubkey(40), + pubkey(41), vec![ BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] }, BlindedHop { blinded_node_id: pubkey(46), encrypted_payload: vec![0; 46] }, From 9e72bd3b73741aeb623365abf42079b242674755 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:50 +0100 Subject: [PATCH 21/22] `rustfmt`: Drop `lightning/src/offers/test_utils.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index a54e5ddce56..6ba0f391509 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -39,7 +39,6 @@ lightning/src/ln/shutdown_tests.rs lightning/src/ln/types.rs lightning/src/ln/wire.rs lightning/src/offers/mod.rs -lightning/src/offers/test_utils.rs lightning/src/routing/mod.rs lightning/src/routing/router.rs lightning/src/routing/scoring.rs From f38c88f1910103745108d2cda569124a6bf03721 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 30 Jan 2025 11:55:53 +0100 Subject: [PATCH 22/22] `rustfmt`: Drop `lightning/src/offers/mod.rs` from exclusion list --- rustfmt_excluded_files | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index 6ba0f391509..7899a65ee67 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -38,7 +38,6 @@ lightning/src/ln/script.rs lightning/src/ln/shutdown_tests.rs lightning/src/ln/types.rs lightning/src/ln/wire.rs -lightning/src/offers/mod.rs lightning/src/routing/mod.rs lightning/src/routing/router.rs lightning/src/routing/scoring.rs