Skip to content

Commit 82364b2

Browse files
Test auto-retry partial failure cases
1 parent b16e041 commit 82364b2

File tree

3 files changed

+220
-3
lines changed

3 files changed

+220
-3
lines changed

lightning/src/ln/channelmanager.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7851,7 +7851,7 @@ pub mod bench {
78517851
let tx_broadcaster = test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new()), blocks: Arc::new(Mutex::new(Vec::new()))};
78527852
let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) };
78537853
let logger_a = test_utils::TestLogger::with_id("node a".to_owned());
7854-
let router = test_utils::TestRouter { network_graph: Arc::new(NetworkGraph::new(genesis_hash, &logger_a)) };
7854+
let router = test_utils::TestRouter::new(Arc::new(NetworkGraph::new(genesis_hash, &logger_a)));
78557855

78567856
let mut config: UserConfig = Default::default();
78577857
config.channel_handshake_config.minimum_depth = 1;

lightning/src/ln/payment_tests.rs

+199-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::ln::msgs;
2222
use crate::ln::msgs::ChannelMessageHandler;
2323
use crate::ln::outbound_payment::Retry;
2424
use crate::routing::gossip::RoutingFees;
25-
use crate::routing::router::{get_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters};
25+
use crate::routing::router::{get_route, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RouteParameters};
2626
use crate::util::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider};
2727
use crate::util::test_utils;
2828
use crate::util::errors::APIError;
@@ -1755,3 +1755,201 @@ fn do_automatic_retries(test: AutoRetry) {
17551755
}
17561756
}
17571757
}
1758+
1759+
#[test]
1760+
fn auto_retry_partial_failure() {
1761+
// Test that we'll retry appropriately on send partial failure and retry partial failure.
1762+
let chanmon_cfgs = create_chanmon_cfgs(2);
1763+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
1764+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
1765+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
1766+
1767+
let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
1768+
let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
1769+
let chan_3_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).0.contents.short_channel_id;
1770+
1771+
// Marshall data to send the payment
1772+
let amt_msat = 20_000;
1773+
let (_, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[1], amt_msat);
1774+
#[cfg(feature = "std")]
1775+
let payment_expiry_secs = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() + 60 * 60;
1776+
#[cfg(not(feature = "std"))]
1777+
let payment_expiry_secs = 60 * 60;
1778+
let mut invoice_features = InvoiceFeatures::empty();
1779+
invoice_features.set_variable_length_onion_required();
1780+
invoice_features.set_payment_secret_required();
1781+
invoice_features.set_basic_mpp_optional();
1782+
let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
1783+
.with_expiry_time(payment_expiry_secs as u64)
1784+
.with_features(invoice_features);
1785+
let route_params = RouteParameters {
1786+
payment_params,
1787+
final_value_msat: amt_msat,
1788+
final_cltv_expiry_delta: TEST_FINAL_CLTV,
1789+
};
1790+
1791+
// Ensure the first monitor update (for the initial send path1 over chan_1) succeeds, but the
1792+
// second (for the initial send path2 over chan_2) fails.
1793+
chanmon_cfgs[0].persister.set_next_update_ret(ChannelMonitorUpdateStatus::Completed);
1794+
chanmon_cfgs[0].persister.set_next_update_ret(ChannelMonitorUpdateStatus::PermanentFailure);
1795+
// Ensure third monitor update (for the retry1's path1 over chan_1) succeeds, but the fourth (for
1796+
// the retry1's path2 over chan_3) fails, and monitor updates succeed after that.
1797+
chanmon_cfgs[0].persister.set_next_update_ret(ChannelMonitorUpdateStatus::Completed);
1798+
chanmon_cfgs[0].persister.set_next_update_ret(ChannelMonitorUpdateStatus::PermanentFailure);
1799+
chanmon_cfgs[0].persister.set_next_update_ret(ChannelMonitorUpdateStatus::Completed);
1800+
1801+
// Configure the initial send, retry1 and retry2's paths.
1802+
let send_route = Route {
1803+
paths: vec![
1804+
vec![RouteHop {
1805+
pubkey: nodes[1].node.get_our_node_id(),
1806+
node_features: channelmanager::provided_node_features(),
1807+
short_channel_id: chan_1_id,
1808+
channel_features: channelmanager::provided_channel_features(),
1809+
fee_msat: amt_msat / 2,
1810+
cltv_expiry_delta: 100,
1811+
}],
1812+
vec![RouteHop {
1813+
pubkey: nodes[1].node.get_our_node_id(),
1814+
node_features: channelmanager::provided_node_features(),
1815+
short_channel_id: chan_2_id,
1816+
channel_features: channelmanager::provided_channel_features(),
1817+
fee_msat: amt_msat / 2,
1818+
cltv_expiry_delta: 100,
1819+
}],
1820+
],
1821+
payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())),
1822+
};
1823+
let retry_1_route = Route {
1824+
paths: vec![
1825+
vec![RouteHop {
1826+
pubkey: nodes[1].node.get_our_node_id(),
1827+
node_features: channelmanager::provided_node_features(),
1828+
short_channel_id: chan_1_id,
1829+
channel_features: channelmanager::provided_channel_features(),
1830+
fee_msat: amt_msat / 4,
1831+
cltv_expiry_delta: 100,
1832+
}],
1833+
vec![RouteHop {
1834+
pubkey: nodes[1].node.get_our_node_id(),
1835+
node_features: channelmanager::provided_node_features(),
1836+
short_channel_id: chan_3_id,
1837+
channel_features: channelmanager::provided_channel_features(),
1838+
fee_msat: amt_msat / 4,
1839+
cltv_expiry_delta: 100,
1840+
}],
1841+
],
1842+
payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())),
1843+
};
1844+
let retry_2_route = Route {
1845+
paths: vec![
1846+
vec![RouteHop {
1847+
pubkey: nodes[1].node.get_our_node_id(),
1848+
node_features: channelmanager::provided_node_features(),
1849+
short_channel_id: chan_1_id,
1850+
channel_features: channelmanager::provided_channel_features(),
1851+
fee_msat: amt_msat / 4,
1852+
cltv_expiry_delta: 100,
1853+
}],
1854+
],
1855+
payment_params: Some(PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())),
1856+
};
1857+
nodes[0].router.expect_find_route(Ok(send_route));
1858+
nodes[0].router.expect_find_route(Ok(retry_1_route));
1859+
nodes[0].router.expect_find_route(Ok(retry_2_route));
1860+
1861+
// Send a payment that will partially fail on send, then partially fail on retry, then succeed.
1862+
nodes[0].node.send_payment_with_retry(payment_hash, &Some(payment_secret), PaymentId(payment_hash.0), route_params, Retry::Attempts(3)).unwrap();
1863+
let closed_chan_events = nodes[0].node.get_and_clear_pending_events();
1864+
assert_eq!(closed_chan_events.len(), 2);
1865+
match closed_chan_events[0] {
1866+
Event::ChannelClosed { .. } => {},
1867+
_ => panic!("Unexpected event"),
1868+
}
1869+
match closed_chan_events[1] {
1870+
Event::ChannelClosed { .. } => {},
1871+
_ => panic!("Unexpected event"),
1872+
}
1873+
1874+
// Pass the first part of the payment along the path.
1875+
check_added_monitors!(nodes[0], 5); // three outbound channel updates succeeded, two permanently failed
1876+
let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events();
1877+
1878+
// First message is the first update_add, remaining messages are broadcasting channel updates and
1879+
// errors for the permfailed channels
1880+
assert_eq!(msg_events.len(), 5);
1881+
let mut payment_event = SendEvent::from_event(msg_events.remove(0));
1882+
1883+
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
1884+
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg);
1885+
check_added_monitors!(nodes[1], 1);
1886+
let (bs_first_raa, bs_first_cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
1887+
1888+
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_first_raa);
1889+
check_added_monitors!(nodes[0], 1);
1890+
let as_second_htlc_updates = SendEvent::from_node(&nodes[0]);
1891+
1892+
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_first_cs);
1893+
check_added_monitors!(nodes[0], 1);
1894+
let as_first_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
1895+
1896+
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_first_raa);
1897+
check_added_monitors!(nodes[1], 1);
1898+
1899+
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &as_second_htlc_updates.msgs[0]);
1900+
nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &as_second_htlc_updates.msgs[1]);
1901+
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_second_htlc_updates.commitment_msg);
1902+
check_added_monitors!(nodes[1], 1);
1903+
let (bs_second_raa, bs_second_cs) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
1904+
1905+
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_raa);
1906+
check_added_monitors!(nodes[0], 1);
1907+
1908+
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_second_cs);
1909+
check_added_monitors!(nodes[0], 1);
1910+
let as_second_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
1911+
1912+
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_second_raa);
1913+
check_added_monitors!(nodes[1], 1);
1914+
1915+
expect_pending_htlcs_forwardable_ignore!(nodes[1]);
1916+
nodes[1].node.process_pending_htlc_forwards();
1917+
expect_payment_claimable!(nodes[1], payment_hash, payment_secret, amt_msat);
1918+
nodes[1].node.claim_funds(payment_preimage);
1919+
expect_payment_claimed!(nodes[1], payment_hash, amt_msat);
1920+
let bs_claim_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
1921+
assert_eq!(bs_claim_update.update_fulfill_htlcs.len(), 1);
1922+
1923+
nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_claim_update.update_fulfill_htlcs[0]);
1924+
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_claim_update.commitment_signed);
1925+
check_added_monitors!(nodes[0], 1);
1926+
let (as_third_raa, as_third_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id());
1927+
1928+
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_third_raa);
1929+
check_added_monitors!(nodes[1], 4);
1930+
let bs_second_claim_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
1931+
1932+
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_third_cs);
1933+
check_added_monitors!(nodes[1], 1);
1934+
let bs_third_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
1935+
1936+
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_third_raa);
1937+
check_added_monitors!(nodes[0], 1);
1938+
1939+
nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_second_claim_update.update_fulfill_htlcs[0]);
1940+
nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_second_claim_update.update_fulfill_htlcs[1]);
1941+
nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_second_claim_update.commitment_signed);
1942+
check_added_monitors!(nodes[0], 1);
1943+
let (as_fourth_raa, as_fourth_cs) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id());
1944+
1945+
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_fourth_raa);
1946+
check_added_monitors!(nodes[1], 1);
1947+
1948+
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_fourth_cs);
1949+
check_added_monitors!(nodes[1], 1);
1950+
let bs_second_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
1951+
1952+
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_raa);
1953+
check_added_monitors!(nodes[0], 1);
1954+
expect_payment_sent!(nodes[0], payment_preimage);
1955+
}

lightning/src/util/test_utils.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::chain::keysinterface;
2020
use crate::ln::channelmanager;
2121
use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
2222
use crate::ln::{msgs, wire};
23+
use crate::ln::msgs::LightningError;
2324
use crate::ln::script::ShutdownScript;
2425
use crate::routing::gossip::NetworkGraph;
2526
use crate::routing::router::{find_route, InFlightHtlcs, Route, RouteHop, RouteParameters, Router, ScorerAccountingForInFlightHtlcs};
@@ -75,11 +76,17 @@ impl chaininterface::FeeEstimator for TestFeeEstimator {
7576

7677
pub struct TestRouter<'a> {
7778
pub network_graph: Arc<NetworkGraph<&'a TestLogger>>,
79+
pub next_routes: Mutex<VecDeque<Result<Route, LightningError>>>,
7880
}
7981

8082
impl<'a> TestRouter<'a> {
8183
pub fn new(network_graph: Arc<NetworkGraph<&'a TestLogger>>) -> Self {
82-
Self { network_graph }
84+
Self { network_graph, next_routes: Mutex::new(VecDeque::new()), }
85+
}
86+
87+
pub fn expect_find_route(&self, result: Result<Route, LightningError>) {
88+
let mut expected_routes = self.next_routes.lock().unwrap();
89+
expected_routes.push_back(result);
8390
}
8491
}
8592

@@ -88,6 +95,9 @@ impl<'a> Router for TestRouter<'a> {
8895
&self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&channelmanager::ChannelDetails]>,
8996
inflight_htlcs: &InFlightHtlcs
9097
) -> Result<Route, msgs::LightningError> {
98+
if let Some(find_route_res) = self.next_routes.lock().unwrap().pop_front() {
99+
return find_route_res
100+
}
91101
let logger = TestLogger::new();
92102
find_route(
93103
payer, params, &self.network_graph, first_hops, &logger,
@@ -101,6 +111,15 @@ impl<'a> Router for TestRouter<'a> {
101111
fn notify_payment_probe_failed(&self, _path: &[&RouteHop], _short_channel_id: u64) {}
102112
}
103113

114+
impl<'a> Drop for TestRouter<'a> {
115+
fn drop(&mut self) {
116+
if std::thread::panicking() {
117+
return;
118+
}
119+
assert!(self.next_routes.lock().unwrap().is_empty());
120+
}
121+
}
122+
104123
pub struct OnlyReadsKeysInterface {}
105124

106125
impl EntropySource for OnlyReadsKeysInterface {

0 commit comments

Comments
 (0)