Skip to content

Commit 6e25648

Browse files
committed
Add tests for send_payment_for_bolt12_invoice
1 parent d164758 commit 6e25648

File tree

2 files changed

+244
-2
lines changed

2 files changed

+244
-2
lines changed

lightning/src/ln/outbound_payment.rs

Lines changed: 243 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ pub enum PaymentSendFailure {
442442
}
443443

444444
/// An error when attempting to pay a BOLT 12 invoice.
445+
#[derive(Clone, Debug, PartialEq, Eq)]
445446
pub(super) enum Bolt12PaymentError {
446447
/// The invoice was not requested.
447448
UnexpectedInvoice,
@@ -1677,7 +1678,10 @@ mod tests {
16771678
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
16781679
use crate::ln::features::{ChannelFeatures, NodeFeatures};
16791680
use crate::ln::msgs::{ErrorAction, LightningError};
1680-
use crate::ln::outbound_payment::{INVOICE_REQUEST_TIMEOUT_TICKS, OutboundPayments, Retry, RetryableSendFailure};
1681+
use crate::ln::outbound_payment::{Bolt12PaymentError, INVOICE_REQUEST_TIMEOUT_TICKS, OutboundPayments, Retry, RetryableSendFailure};
1682+
use crate::offers::invoice::DEFAULT_RELATIVE_EXPIRY;
1683+
use crate::offers::offer::OfferBuilder;
1684+
use crate::offers::test_utils::*;
16811685
use crate::routing::gossip::NetworkGraph;
16821686
use crate::routing::router::{InFlightHtlcs, Path, PaymentParameters, Route, RouteHop, RouteParameters};
16831687
use crate::sync::{Arc, Mutex, RwLock};
@@ -1916,4 +1920,242 @@ mod tests {
19161920

19171921
assert!(outbound_payments.add_new_awaiting_invoice(payment_id).is_err());
19181922
}
1923+
1924+
#[cfg(feature = "std")]
1925+
#[test]
1926+
fn fails_sending_payment_for_expired_bolt12_invoice() {
1927+
let logger = test_utils::TestLogger::new();
1928+
let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger));
1929+
let scorer = RwLock::new(test_utils::TestScorer::new());
1930+
let router = test_utils::TestRouter::new(network_graph, &scorer);
1931+
let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet);
1932+
1933+
let pending_events = Mutex::new(VecDeque::new());
1934+
let outbound_payments = OutboundPayments::new();
1935+
let payment_id = PaymentId([0; 32]);
1936+
1937+
assert!(outbound_payments.add_new_awaiting_invoice(payment_id).is_ok());
1938+
assert!(outbound_payments.has_pending_payments());
1939+
1940+
let created_at = now() - DEFAULT_RELATIVE_EXPIRY;
1941+
let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
1942+
.amount_msats(1000)
1943+
.build().unwrap()
1944+
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1945+
.build().unwrap()
1946+
.sign(payer_sign).unwrap()
1947+
.respond_with_no_std(payment_paths(), payment_hash(), created_at).unwrap()
1948+
.build().unwrap()
1949+
.sign(recipient_sign).unwrap();
1950+
1951+
assert_eq!(
1952+
outbound_payments.send_payment_for_bolt12_invoice(
1953+
&invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager,
1954+
&&keys_manager, 0, &&logger, &pending_events, |_| panic!()
1955+
),
1956+
Ok(()),
1957+
);
1958+
assert!(!outbound_payments.has_pending_payments());
1959+
1960+
let payment_hash = invoice.payment_hash();
1961+
let reason = Some(PaymentFailureReason::PaymentExpired);
1962+
1963+
assert!(!pending_events.lock().unwrap().is_empty());
1964+
assert_eq!(
1965+
pending_events.lock().unwrap().pop_front(),
1966+
Some((Event::PaymentFailed { payment_id, payment_hash, reason }, None)),
1967+
);
1968+
assert!(pending_events.lock().unwrap().is_empty());
1969+
}
1970+
1971+
#[test]
1972+
fn fails_finding_route_for_bolt12_invoice() {
1973+
let logger = test_utils::TestLogger::new();
1974+
let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger));
1975+
let scorer = RwLock::new(test_utils::TestScorer::new());
1976+
let router = test_utils::TestRouter::new(network_graph, &scorer);
1977+
let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet);
1978+
1979+
let pending_events = Mutex::new(VecDeque::new());
1980+
let outbound_payments = OutboundPayments::new();
1981+
let payment_id = PaymentId([0; 32]);
1982+
1983+
assert!(outbound_payments.add_new_awaiting_invoice(payment_id).is_ok());
1984+
assert!(outbound_payments.has_pending_payments());
1985+
1986+
let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
1987+
.amount_msats(1000)
1988+
.build().unwrap()
1989+
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
1990+
.build().unwrap()
1991+
.sign(payer_sign).unwrap()
1992+
.respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
1993+
.build().unwrap()
1994+
.sign(recipient_sign).unwrap();
1995+
1996+
router.expect_find_route(
1997+
RouteParameters {
1998+
payment_params: PaymentParameters::from_bolt12_invoice(&invoice),
1999+
final_value_msat: invoice.amount_msats(),
2000+
},
2001+
Err(LightningError { err: String::new(), action: ErrorAction::IgnoreError }),
2002+
);
2003+
2004+
assert_eq!(
2005+
outbound_payments.send_payment_for_bolt12_invoice(
2006+
&invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager,
2007+
&&keys_manager, 0, &&logger, &pending_events, |_| panic!()
2008+
),
2009+
Ok(()),
2010+
);
2011+
assert!(!outbound_payments.has_pending_payments());
2012+
2013+
let payment_hash = invoice.payment_hash();
2014+
let reason = Some(PaymentFailureReason::RouteNotFound);
2015+
2016+
assert!(!pending_events.lock().unwrap().is_empty());
2017+
assert_eq!(
2018+
pending_events.lock().unwrap().pop_front(),
2019+
Some((Event::PaymentFailed { payment_id, payment_hash, reason }, None)),
2020+
);
2021+
assert!(pending_events.lock().unwrap().is_empty());
2022+
}
2023+
2024+
#[test]
2025+
fn fails_paying_for_bolt12_invoice() {
2026+
let logger = test_utils::TestLogger::new();
2027+
let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger));
2028+
let scorer = RwLock::new(test_utils::TestScorer::new());
2029+
let router = test_utils::TestRouter::new(network_graph, &scorer);
2030+
let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet);
2031+
2032+
let pending_events = Mutex::new(VecDeque::new());
2033+
let outbound_payments = OutboundPayments::new();
2034+
let payment_id = PaymentId([0; 32]);
2035+
2036+
assert!(outbound_payments.add_new_awaiting_invoice(payment_id).is_ok());
2037+
assert!(outbound_payments.has_pending_payments());
2038+
2039+
let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
2040+
.amount_msats(1000)
2041+
.build().unwrap()
2042+
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
2043+
.build().unwrap()
2044+
.sign(payer_sign).unwrap()
2045+
.respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
2046+
.build().unwrap()
2047+
.sign(recipient_sign).unwrap();
2048+
2049+
router.expect_find_route(
2050+
RouteParameters {
2051+
payment_params: PaymentParameters::from_bolt12_invoice(&invoice),
2052+
final_value_msat: invoice.amount_msats(),
2053+
},
2054+
Ok(Route {
2055+
paths: vec![],
2056+
payment_params: Some(PaymentParameters::from_bolt12_invoice(&invoice)),
2057+
})
2058+
);
2059+
2060+
assert_eq!(
2061+
outbound_payments.send_payment_for_bolt12_invoice(
2062+
&invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager,
2063+
&&keys_manager, 0, &&logger, &pending_events, |_| panic!()
2064+
),
2065+
Ok(()),
2066+
);
2067+
assert!(!outbound_payments.has_pending_payments());
2068+
2069+
let payment_hash = invoice.payment_hash();
2070+
let reason = Some(PaymentFailureReason::UnexpectedError);
2071+
2072+
assert!(!pending_events.lock().unwrap().is_empty());
2073+
assert_eq!(
2074+
pending_events.lock().unwrap().pop_front(),
2075+
Some((Event::PaymentFailed { payment_id, payment_hash, reason }, None)),
2076+
);
2077+
assert!(pending_events.lock().unwrap().is_empty());
2078+
}
2079+
2080+
#[test]
2081+
fn sends_payment_for_bolt12_invoice() {
2082+
let logger = test_utils::TestLogger::new();
2083+
let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger));
2084+
let scorer = RwLock::new(test_utils::TestScorer::new());
2085+
let router = test_utils::TestRouter::new(network_graph, &scorer);
2086+
let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet);
2087+
2088+
let pending_events = Mutex::new(VecDeque::new());
2089+
let outbound_payments = OutboundPayments::new();
2090+
let payment_id = PaymentId([0; 32]);
2091+
2092+
let invoice = OfferBuilder::new("foo".into(), recipient_pubkey())
2093+
.amount_msats(1000)
2094+
.build().unwrap()
2095+
.request_invoice(vec![1; 32], payer_pubkey()).unwrap()
2096+
.build().unwrap()
2097+
.sign(payer_sign).unwrap()
2098+
.respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap()
2099+
.build().unwrap()
2100+
.sign(recipient_sign).unwrap();
2101+
2102+
router.expect_find_route(
2103+
RouteParameters {
2104+
payment_params: PaymentParameters::from_bolt12_invoice(&invoice),
2105+
final_value_msat: invoice.amount_msats(),
2106+
},
2107+
Ok(Route {
2108+
paths: vec![
2109+
Path {
2110+
hops: vec![
2111+
RouteHop {
2112+
pubkey: recipient_pubkey(),
2113+
node_features: NodeFeatures::empty(),
2114+
short_channel_id: 42,
2115+
channel_features: ChannelFeatures::empty(),
2116+
fee_msat: invoice.amount_msats(),
2117+
cltv_expiry_delta: 0,
2118+
}
2119+
],
2120+
blinded_tail: None,
2121+
}
2122+
],
2123+
payment_params: Some(PaymentParameters::from_bolt12_invoice(&invoice)),
2124+
})
2125+
);
2126+
2127+
assert!(!outbound_payments.has_pending_payments());
2128+
assert_eq!(
2129+
outbound_payments.send_payment_for_bolt12_invoice(
2130+
&invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager,
2131+
&&keys_manager, 0, &&logger, &pending_events, |_| panic!()
2132+
),
2133+
Err(Bolt12PaymentError::UnexpectedInvoice),
2134+
);
2135+
assert!(!outbound_payments.has_pending_payments());
2136+
assert!(pending_events.lock().unwrap().is_empty());
2137+
2138+
assert!(outbound_payments.add_new_awaiting_invoice(payment_id).is_ok());
2139+
assert!(outbound_payments.has_pending_payments());
2140+
2141+
assert_eq!(
2142+
outbound_payments.send_payment_for_bolt12_invoice(
2143+
&invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager,
2144+
&&keys_manager, 0, &&logger, &pending_events, |_| Ok(())
2145+
),
2146+
Ok(()),
2147+
);
2148+
assert!(outbound_payments.has_pending_payments());
2149+
assert!(pending_events.lock().unwrap().is_empty());
2150+
2151+
assert_eq!(
2152+
outbound_payments.send_payment_for_bolt12_invoice(
2153+
&invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager,
2154+
&&keys_manager, 0, &&logger, &pending_events, |_| panic!()
2155+
),
2156+
Err(Bolt12PaymentError::DuplicateInvoice),
2157+
);
2158+
assert!(outbound_payments.has_pending_payments());
2159+
assert!(pending_events.lock().unwrap().is_empty());
2160+
}
19192161
}

lightning/src/offers/invoice.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ use crate::prelude::*;
129129
#[cfg(feature = "std")]
130130
use std::time::SystemTime;
131131

132-
const DEFAULT_RELATIVE_EXPIRY: Duration = Duration::from_secs(7200);
132+
pub(crate) const DEFAULT_RELATIVE_EXPIRY: Duration = Duration::from_secs(7200);
133133

134134
/// Tag for the hash function used when signing a [`Bolt12Invoice`]'s merkle root.
135135
pub const SIGNATURE_TAG: &'static str = concat!("lightning", "invoice", "signature");

0 commit comments

Comments
 (0)