From fd596c31b504adfddf8478ef59451a62a3d2c597 Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Fri, 12 Jul 2024 11:14:18 -0500 Subject: [PATCH] Pass Nonce directly to InvoiceRequestBuilder When using InvoiceRequestBuilder::deriving_payer_id, the nonce generated needs to be the same one included in any reply path. This is because the nonce is used along with the invoice request TLVs to derive a payer id. While this data is also included in the payer_metadata, including it in the blinded path would allow reducing the amount of data needed there to just enough to provide entropy (i.e., 16 bytes). This is more important for Refund because it can be transmitted via a QR code. But using the same payer_metadata structure for both InvoiceRequest and Refund would be beneficial to avoid more code. --- lightning/src/ln/channelmanager.rs | 3 ++- lightning/src/offers/invoice_request.rs | 22 ++++++++++------------ lightning/src/offers/offer.rs | 24 ++++++++---------------- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 837a8927d..6e6b0ceb6 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -8976,8 +8976,9 @@ where let entropy = &*self.entropy_source; let secp_ctx = &self.secp_ctx; + let nonce = Nonce::from_entropy_source(entropy); let builder: InvoiceRequestBuilder = offer - .request_invoice_deriving_payer_id(expanded_key, entropy, secp_ctx, payment_id)? + .request_invoice_deriving_payer_id(expanded_key, nonce, secp_ctx, payment_id)? .into(); let builder = builder.chain_hash(self.chain_hash)?; diff --git a/lightning/src/offers/invoice_request.rs b/lightning/src/offers/invoice_request.rs index 39eb157d7..b8e47bac5 100644 --- a/lightning/src/offers/invoice_request.rs +++ b/lightning/src/offers/invoice_request.rs @@ -61,8 +61,6 @@ use bitcoin::blockdata::constants::ChainHash; use bitcoin::network::Network; use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, self}; use bitcoin::secp256k1::schnorr::Signature; -use core::ops::Deref; -use crate::sign::EntropySource; use crate::io; use crate::blinded_path::BlindedPath; use crate::ln::types::PaymentHash; @@ -171,11 +169,10 @@ macro_rules! invoice_request_explicit_payer_id_builder_methods { ($self: ident, } #[cfg_attr(c_bindings, allow(dead_code))] - pub(super) fn deriving_metadata( - offer: &'a Offer, payer_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES, + pub(super) fn deriving_metadata( + offer: &'a Offer, payer_id: PublicKey, expanded_key: &ExpandedKey, nonce: Nonce, payment_id: PaymentId, - ) -> Self where ES::Target: EntropySource { - let nonce = Nonce::from_entropy_source(entropy_source); + ) -> Self { let payment_id = Some(payment_id); let derivation_material = MetadataMaterial::new(nonce, expanded_key, IV_BYTES, payment_id); let metadata = Metadata::Derived(derivation_material); @@ -201,11 +198,10 @@ macro_rules! invoice_request_derived_payer_id_builder_methods { ( $self: ident, $self_type: ty, $secp_context: ty ) => { #[cfg_attr(c_bindings, allow(dead_code))] - pub(super) fn deriving_payer_id( - offer: &'a Offer, expanded_key: &ExpandedKey, entropy_source: ES, + pub(super) fn deriving_payer_id( + offer: &'a Offer, expanded_key: &ExpandedKey, nonce: Nonce, secp_ctx: &'b Secp256k1<$secp_context>, payment_id: PaymentId - ) -> Self where ES::Target: EntropySource { - let nonce = Nonce::from_entropy_source(entropy_source); + ) -> Self { let payment_id = Some(payment_id); let derivation_material = MetadataMaterial::new(nonce, expanded_key, IV_BYTES, payment_id); let metadata = Metadata::DerivedSigningPubkey(derivation_material); @@ -1403,6 +1399,7 @@ mod tests { let payer_id = payer_pubkey(); let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32])); let entropy = FixedEntropy {}; + let nonce = Nonce::from_entropy_source(&entropy); let secp_ctx = Secp256k1::new(); let payment_id = PaymentId([1; 32]); @@ -1410,7 +1407,7 @@ mod tests { .amount_msats(1000) .build().unwrap(); let invoice_request = offer - .request_invoice_deriving_metadata(payer_id, &expanded_key, &entropy, payment_id) + .request_invoice_deriving_metadata(payer_id, &expanded_key, nonce, payment_id) .unwrap() .build().unwrap() .sign(payer_sign).unwrap(); @@ -1476,6 +1473,7 @@ mod tests { fn builds_invoice_request_with_derived_payer_id() { let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32])); let entropy = FixedEntropy {}; + let nonce = Nonce::from_entropy_source(&entropy); let secp_ctx = Secp256k1::new(); let payment_id = PaymentId([1; 32]); @@ -1483,7 +1481,7 @@ mod tests { .amount_msats(1000) .build().unwrap(); let invoice_request = offer - .request_invoice_deriving_payer_id(&expanded_key, &entropy, &secp_ctx, payment_id) + .request_invoice_deriving_payer_id(&expanded_key, nonce, &secp_ctx, payment_id) .unwrap() .build_and_sign() .unwrap(); diff --git a/lightning/src/offers/offer.rs b/lightning/src/offers/offer.rs index 94d5175a5..b5e9154d5 100644 --- a/lightning/src/offers/offer.rs +++ b/lightning/src/offers/offer.rs @@ -82,10 +82,8 @@ use bitcoin::network::Network; use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, self}; use core::hash::{Hash, Hasher}; use core::num::NonZeroU64; -use core::ops::Deref; use core::str::FromStr; use core::time::Duration; -use crate::sign::EntropySource; use crate::io; use crate::blinded_path::BlindedPath; use crate::ln::channelmanager::PaymentId; @@ -699,25 +697,22 @@ macro_rules! request_invoice_derived_payer_id { ($self: ident, $builder: ty) => /// [`Bolt12Invoice::verify`]: crate::offers::invoice::Bolt12Invoice::verify /// [`ExpandedKey`]: crate::ln::inbound_payment::ExpandedKey pub fn request_invoice_deriving_payer_id< - 'a, 'b, ES: Deref, + 'a, 'b, #[cfg(not(c_bindings))] T: secp256k1::Signing >( - &'a $self, expanded_key: &ExpandedKey, entropy_source: ES, + &'a $self, expanded_key: &ExpandedKey, nonce: Nonce, #[cfg(not(c_bindings))] secp_ctx: &'b Secp256k1, #[cfg(c_bindings)] secp_ctx: &'b Secp256k1, payment_id: PaymentId - ) -> Result<$builder, Bolt12SemanticError> - where - ES::Target: EntropySource, - { + ) -> Result<$builder, Bolt12SemanticError> { if $self.offer_features().requires_unknown_bits() { return Err(Bolt12SemanticError::UnknownRequiredFeatures); } - Ok(<$builder>::deriving_payer_id($self, expanded_key, entropy_source, secp_ctx, payment_id)) + Ok(<$builder>::deriving_payer_id($self, expanded_key, nonce, secp_ctx, payment_id)) } } } @@ -728,18 +723,15 @@ macro_rules! request_invoice_explicit_payer_id { ($self: ident, $builder: ty) => /// Useful for recurring payments using the same `payer_id` with different invoices. /// /// [`InvoiceRequest::payer_id`]: crate::offers::invoice_request::InvoiceRequest::payer_id - pub fn request_invoice_deriving_metadata( - &$self, payer_id: PublicKey, expanded_key: &ExpandedKey, entropy_source: ES, + pub fn request_invoice_deriving_metadata( + &$self, payer_id: PublicKey, expanded_key: &ExpandedKey, nonce: Nonce, payment_id: PaymentId - ) -> Result<$builder, Bolt12SemanticError> - where - ES::Target: EntropySource, - { + ) -> Result<$builder, Bolt12SemanticError> { if $self.offer_features().requires_unknown_bits() { return Err(Bolt12SemanticError::UnknownRequiredFeatures); } - Ok(<$builder>::deriving_metadata($self, payer_id, expanded_key, entropy_source, payment_id)) + Ok(<$builder>::deriving_metadata($self, payer_id, expanded_key, nonce, payment_id)) } /// Creates an [`InvoiceRequestBuilder`] for the offer with the given `metadata` and `payer_id`, -- 2.39.5