Skip to content

Commit 49486e6

Browse files
committed
Authenticate Bolt12RefundContext with payment hash
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.
1 parent 3ddac04 commit 49486e6

File tree

4 files changed

+26
-8
lines changed

4 files changed

+26
-8
lines changed

fuzz/src/refund_deser.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
7171
) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
7272
let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32]));
7373
let entropy_source = Randomness {};
74-
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
74+
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {
75+
payment_hash: PaymentHash([42u8; 32]),
76+
});
7577
let nonce = Nonce::from_entropy_source(&entropy_source);
7678
let hmac = payment_context.hmac_for_offer_payment(nonce, &expanded_key);
7779
let payee_tlvs = ReceiveTlvs {

lightning/src/blinded_path/payment.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::io::Cursor;
2121
use crate::types::payment::PaymentSecret;
2222
use crate::ln::channel_state::CounterpartyForwardingInfo;
2323
use crate::types::features::BlindedHopFeatures;
24+
use crate::types::payment::PaymentHash;
2425
use crate::ln::msgs::DecodeError;
2526
use crate::ln::onion_utils;
2627
use crate::offers::invoice_request::InvoiceRequestFields;
@@ -360,7 +361,10 @@ pub struct Bolt12OfferContext {
360361
///
361362
/// [`Refund`]: crate::offers::refund::Refund
362363
#[derive(Clone, Debug, Eq, PartialEq)]
363-
pub struct Bolt12RefundContext {}
364+
pub struct Bolt12RefundContext {
365+
/// The [`PaymentHash`] used in the invoice.
366+
pub payment_hash: PaymentHash,
367+
}
364368

365369
impl PaymentContext {
366370
pub(crate) fn unknown() -> Self {
@@ -634,7 +638,9 @@ impl_writeable_tlv_based!(Bolt12OfferContext, {
634638
(2, invoice_request, required),
635639
});
636640

637-
impl_writeable_tlv_based!(Bolt12RefundContext, {});
641+
impl_writeable_tlv_based!(Bolt12RefundContext, {
642+
(0, payment_hash, required),
643+
});
638644

639645
#[cfg(test)]
640646
mod tests {

lightning/src/ln/channelmanager.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -10173,7 +10173,9 @@ where
1017310173

1017410174
match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) {
1017510175
Ok((payment_hash, payment_secret)) => {
10176-
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
10176+
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {
10177+
payment_hash,
10178+
});
1017710179
let payment_paths = self.create_blinded_payment_paths(
1017810180
amount_msats, payment_secret, payment_context
1017910181
)

lightning/src/ln/offers_tests.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -654,8 +654,10 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() {
654654
}
655655
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
656656

657-
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
658657
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
658+
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {
659+
payment_hash: invoice.payment_hash(),
660+
});
659661

660662
connect_peers(alice, charlie);
661663

@@ -783,8 +785,10 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() {
783785
}
784786
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
785787

786-
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
787788
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
789+
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {
790+
payment_hash: invoice.payment_hash(),
791+
});
788792

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

891-
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
892895
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();
896+
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {
897+
payment_hash: invoice.payment_hash(),
898+
});
893899

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

21192125
// David initiates paying the first invoice
2120-
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
21212126
let (invoice1, _) = extract_invoice(david, &onion_message);
2127+
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {
2128+
payment_hash: invoice.payment_hash(),
2129+
});
21222130

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

0 commit comments

Comments
 (0)