Skip to content

Commit

Permalink
Merge pull request #2917 from jkczyz/2024-02-refund-unsupported-chain
Browse files Browse the repository at this point in the history
Fail `request_refund_payment` for unsupported chain
  • Loading branch information
TheBlueMatt authored Mar 12, 2024
2 parents 6d5c952 + 228e72c commit aa334d5
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 2 deletions.
11 changes: 9 additions & 2 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7830,6 +7830,7 @@ where
/// Errors if:
/// - a duplicate `payment_id` is provided given the caveats in the aforementioned link,
/// - the provided parameters are invalid for the offer,
/// - the offer is for an unsupported chain, or
/// - the parameterized [`Router`] is unable to create a blinded reply path for the invoice
/// request.
///
Expand Down Expand Up @@ -7918,8 +7919,10 @@ where
///
/// # Errors
///
/// Errors if the parameterized [`Router`] is unable to create a blinded payment path or reply
/// path for the invoice.
/// Errors if:
/// - the refund is for an unsupported chain, or
/// - the parameterized [`Router`] is unable to create a blinded payment path or reply path for
/// the invoice.
///
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
pub fn request_refund_payment(&self, refund: &Refund) -> Result<(), Bolt12SemanticError> {
Expand All @@ -7930,6 +7933,10 @@ where
let amount_msats = refund.amount_msats();
let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32;

if refund.chain() != self.chain_hash {
return Err(Bolt12SemanticError::UnsupportedChain);
}

match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) {
Ok((payment_hash, payment_secret)) => {
let payment_paths = self.create_blinded_payment_paths(amount_msats, payment_secret)
Expand Down
56 changes: 56 additions & 0 deletions lightning/src/ln/offers_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
//! Nodes without channels are disconnected and connected as needed to ensure that deterministic
//! blinded paths are used.

use bitcoin::network::constants::Network;
use core::time::Duration;
use crate::blinded_path::BlindedPath;
use crate::events::{Event, MessageSendEventsProvider, PaymentPurpose};
Expand Down Expand Up @@ -732,6 +733,61 @@ fn fails_creating_refund_without_blinded_paths() {
assert!(nodes[0].node.list_recent_payments().is_empty());
}

/// Fails creating an invoice request when the offer contains an unsupported chain.
#[test]
fn fails_creating_invoice_request_for_unsupported_chain() {
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);

create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);

let alice = &nodes[0];
let bob = &nodes[1];

let offer = alice.node
.create_offer_builder("coffee".to_string()).unwrap()
.clear_chains()
.chain(Network::Signet)
.build().unwrap();

let payment_id = PaymentId([1; 32]);
match bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None) {
Ok(_) => panic!("Expected error"),
Err(e) => assert_eq!(e, Bolt12SemanticError::UnsupportedChain),
}
}

/// Fails requesting a payment when the refund contains an unsupported chain.
#[test]
fn fails_sending_invoice_with_unsupported_chain_for_refund() {
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);

create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);

let alice = &nodes[0];
let bob = &nodes[1];

let absolute_expiry = Duration::from_secs(u64::MAX);
let payment_id = PaymentId([1; 32]);
let refund = bob.node
.create_refund_builder(
"refund".to_string(), 10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None
)
.unwrap()
.chain(Network::Signet)
.build().unwrap();

match alice.node.request_refund_payment(&refund) {
Ok(_) => panic!("Expected error"),
Err(e) => assert_eq!(e, Bolt12SemanticError::UnsupportedChain),
}
}

/// Fails creating an invoice request when a blinded reply path cannot be created without exposing
/// the node's id.
#[test]
Expand Down
6 changes: 6 additions & 0 deletions lightning/src/offers/offer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,12 @@ macro_rules! offer_builder_test_methods { (
$return_value
}

#[cfg_attr(c_bindings, allow(dead_code))]
pub(crate) fn clear_chains($($self_mut)* $self: $self_type) -> $return_type {
$self.offer.chains = None;
$return_value
}

#[cfg_attr(c_bindings, allow(dead_code))]
pub(crate) fn clear_paths($($self_mut)* $self: $self_type) -> $return_type {
$self.offer.paths = None;
Expand Down

0 comments on commit aa334d5

Please sign in to comment.