]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Add an HMAC to OffersContext::OutboundPayment
authorJeffrey Czyz <jkczyz@gmail.com>
Thu, 18 Jul 2024 16:45:09 +0000 (11:45 -0500)
committerJeffrey Czyz <jkczyz@gmail.com>
Wed, 14 Aug 2024 15:42:17 +0000 (10:42 -0500)
When receiving an InvoiceError in response to an InvoiceRequest, the
corresponding payment should be abandoned. Add an HMAC to
OffersContext::OutboundPayment such that the payment ID can be
authenticated prior to abandoning the payment.

lightning/src/blinded_path/message.rs
lightning/src/ln/channelmanager.rs

index 47444eb900d000a3dd7be2856aa190ca22bfc924..313ac56bfcf684581620535c99c6cba37959a0cf 100644 (file)
@@ -16,6 +16,8 @@ use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
 #[allow(unused_imports)]
 use crate::prelude::*;
 
+use bitcoin::hashes::hmac::Hmac;
+use bitcoin::hashes::sha256::Hash as Sha256;
 use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode, NextMessageHop, NodeIdLookUp};
 use crate::blinded_path::utils;
 use crate::io;
@@ -146,6 +148,12 @@ pub enum OffersContext {
                /// [`Refund`]: crate::offers::refund::Refund
                /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
                nonce: Nonce,
+
+               /// Authentication code for the [`PaymentId`], which should be checked when the context is
+               /// used with an [`InvoiceError`].
+               ///
+               /// [`InvoiceError`]: crate::offers::invoice_error::InvoiceError
+               hmac: Hmac<Sha256>,
        },
        /// Context used by a [`BlindedPath`] as a reply path for a [`Bolt12Invoice`].
        ///
@@ -173,6 +181,7 @@ impl_writeable_tlv_based_enum!(OffersContext,
        (1, OutboundPayment) => {
                (0, payment_id, required),
                (1, nonce, required),
+               (2, hmac, required),
        },
        (2, InboundPayment) => {
                (0, payment_hash, required),
index 4ce3ebc37fc26b807b0c52eb74050def887b5604..b359df9e5ed5988d559a2d8bb09e04036e4092a8 100644 (file)
@@ -68,6 +68,7 @@ use crate::offers::nonce::Nonce;
 use crate::offers::offer::{Offer, OfferBuilder};
 use crate::offers::parse::Bolt12SemanticError;
 use crate::offers::refund::{Refund, RefundBuilder};
+use crate::offers::signer;
 use crate::onion_message::async_payments::{AsyncPaymentsMessage, HeldHtlcAvailable, ReleaseHeldHtlc, AsyncPaymentsMessageHandler};
 use crate::onion_message::messenger::{new_pending_onion_message, Destination, MessageRouter, PendingOnionMessage, Responder, ResponseInstruction};
 use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
@@ -4227,7 +4228,7 @@ where
                        None if invoice.is_for_refund_without_paths() => {
                                invoice.verify_using_metadata(expanded_key, secp_ctx)
                        },
-                       Some(&OffersContext::OutboundPayment { payment_id, nonce }) => {
+                       Some(&OffersContext::OutboundPayment { payment_id, nonce, .. }) => {
                                invoice.verify_using_payer_data(payment_id, nonce, expanded_key, secp_ctx)
                        },
                        _ => Err(()),
@@ -8886,7 +8887,8 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
                let secp_ctx = &$self.secp_ctx;
 
                let nonce = Nonce::from_entropy_source(entropy);
-               let context = OffersContext::OutboundPayment { payment_id, nonce };
+               let hmac = signer::hmac_for_payment_id(payment_id, nonce, expanded_key);
+               let context = OffersContext::OutboundPayment { payment_id, nonce, hmac };
                let path = $self.create_blinded_paths_using_absolute_expiry(context, Some(absolute_expiry))
                        .and_then(|paths| paths.into_iter().next().ok_or(()))
                        .map_err(|_| Bolt12SemanticError::MissingPaths)?;
@@ -9021,7 +9023,8 @@ where
                };
                let invoice_request = builder.build_and_sign()?;
 
-               let context = OffersContext::OutboundPayment { payment_id, nonce };
+               let hmac = signer::hmac_for_payment_id(payment_id, nonce, expanded_key);
+               let context = OffersContext::OutboundPayment { payment_id, nonce, hmac };
                let reply_paths = self.create_blinded_paths(context)
                        .map_err(|_| Bolt12SemanticError::MissingPaths)?;