Skip to content

Commit

Permalink
Authenticate Bolt12RefundContext with payment hash
Browse files Browse the repository at this point in the history
Bolt12RefundContext didn't contain any data, so there wasn't anything to
use to authenticate it. Include the invoice's payment hash so that it
can only be used for the corresponding payment.
  • Loading branch information
jkczyz committed Dec 2, 2024
1 parent 3ddac04 commit c371f95
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 8 deletions.
4 changes: 3 additions & 1 deletion fuzz/src/refund_deser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
let entropy_source = Randomness {};
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {
payment_hash: PaymentHash([42u8; 32]),
});
let nonce = Nonce::from_entropy_source(&entropy_source);
let hmac = payment_context.hmac_for_offer_payment(nonce, &expanded_key);
let payee_tlvs = ReceiveTlvs {
Expand Down
10 changes: 8 additions & 2 deletions lightning/src/blinded_path/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::io::Cursor;
use crate::types::payment::PaymentSecret;
use crate::ln::channel_state::CounterpartyForwardingInfo;
use crate::types::features::BlindedHopFeatures;
use crate::types::payment::PaymentHash;
use crate::ln::msgs::DecodeError;
use crate::ln::onion_utils;
use crate::offers::invoice_request::InvoiceRequestFields;
Expand Down Expand Up @@ -360,7 +361,10 @@ pub struct Bolt12OfferContext {
///
/// [`Refund`]: crate::offers::refund::Refund
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Bolt12RefundContext {}
pub struct Bolt12RefundContext {
/// The [`PaymentHash`] used in the invoice.
pub payment_hash: PaymentHash,
}

impl PaymentContext {
pub(crate) fn unknown() -> Self {
Expand Down Expand Up @@ -634,7 +638,9 @@ impl_writeable_tlv_based!(Bolt12OfferContext, {
(2, invoice_request, required),
});

impl_writeable_tlv_based!(Bolt12RefundContext, {});
impl_writeable_tlv_based!(Bolt12RefundContext, {
(0, payment_hash, required),
});

#[cfg(test)]
mod tests {
Expand Down
4 changes: 3 additions & 1 deletion lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10173,7 +10173,9 @@ where

match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) {
Ok((payment_hash, payment_secret)) => {
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {
payment_hash,
});
let payment_paths = self.create_blinded_payment_paths(
amount_msats, payment_secret, payment_context
)
Expand Down
16 changes: 12 additions & 4 deletions lightning/src/ln/offers_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -654,8 +654,10 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() {
}
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);

let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {
payment_hash: expected_invoice.payment_hash(),
});

connect_peers(alice, charlie);

Expand Down Expand Up @@ -783,8 +785,10 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() {
}
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);

let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {
payment_hash: expected_invoice.payment_hash(),
});

let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
bob.onion_messenger.handle_onion_message(alice_id, &onion_message);
Expand Down Expand Up @@ -888,8 +892,10 @@ fn pays_for_refund_without_blinded_paths() {
assert!(refund.paths().is_empty());
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);

let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {
payment_hash: expected_invoice.payment_hash(),
});

let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
bob.onion_messenger.handle_onion_message(alice_id, &onion_message);
Expand Down Expand Up @@ -2117,8 +2123,10 @@ fn fails_paying_invoice_more_than_once() {
david.onion_messenger.handle_onion_message(charlie_id, &onion_message);

// David initiates paying the first invoice
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
let (invoice1, _) = extract_invoice(david, &onion_message);
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {
payment_hash: invoice1.payment_hash(),
});

route_bolt12_payment(david, &[charlie, bob, alice], &invoice1);
expect_recent_payment!(david, RecentPaymentDetails::Pending, payment_id);
Expand Down

0 comments on commit c371f95

Please sign in to comment.