Skip to content

Commit f2f90d5

Browse files
Fix PaymentPathFailed generation and scid on initial send
1 parent 1dcb3ec commit f2f90d5

File tree

1 file changed

+97
-7
lines changed

1 file changed

+97
-7
lines changed

lightning/src/ln/outbound_payment.rs

Lines changed: 97 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -782,13 +782,13 @@ impl OutboundPayments {
782782
debug_assert_eq!(paths.len(), path_results.len());
783783
for (path, path_res) in paths.into_iter().zip(path_results) {
784784
if let Err(e) = path_res {
785-
let failed_scid = if let APIError::InvalidRoute { .. } = e {
786-
None
787-
} else {
785+
if let APIError::MonitorUpdateInProgress = e { continue }
786+
let mut failed_scid = None;
787+
if let APIError::ChannelUnavailable { .. } = e {
788788
let scid = path[0].short_channel_id;
789+
failed_scid = Some(scid);
789790
route_params.payment_params.previously_failed_channels.push(scid);
790-
Some(scid)
791-
};
791+
}
792792
events.push(events::Event::PaymentPathFailed {
793793
payment_id: Some(payment_id),
794794
payment_hash,
@@ -1353,12 +1353,14 @@ mod tests {
13531353

13541354
use crate::ln::PaymentHash;
13551355
use crate::ln::channelmanager::PaymentId;
1356+
use crate::ln::features::{ChannelFeatures, NodeFeatures};
13561357
use crate::ln::msgs::{ErrorAction, LightningError};
13571358
use crate::ln::outbound_payment::{OutboundPayments, Retry, RetryableSendFailure};
13581359
use crate::routing::gossip::NetworkGraph;
1359-
use crate::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteParameters};
1360+
use crate::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteHop, RouteParameters};
13601361
use crate::sync::{Arc, Mutex};
1361-
use crate::util::events::Event;
1362+
use crate::util::errors::APIError;
1363+
use crate::util::events::{Event, PathFailure};
13621364
use crate::util::test_utils;
13631365

13641366
#[test]
@@ -1455,4 +1457,92 @@ mod tests {
14551457
} else { panic!("Unexpected error"); }
14561458
}
14571459
}
1460+
1461+
#[test]
1462+
fn initial_send_payment_path_failed_evs() {
1463+
let outbound_payments = OutboundPayments::new();
1464+
let logger = test_utils::TestLogger::new();
1465+
let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
1466+
let network_graph = Arc::new(NetworkGraph::new(genesis_hash, &logger));
1467+
let scorer = Mutex::new(test_utils::TestScorer::new());
1468+
let router = test_utils::TestRouter::new(network_graph, &scorer);
1469+
let secp_ctx = Secp256k1::new();
1470+
let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet);
1471+
1472+
let sender_pk = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
1473+
let receiver_pk = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[43; 32]).unwrap());
1474+
let payment_params = PaymentParameters::from_node_id(sender_pk, 0);
1475+
let route_params = RouteParameters {
1476+
payment_params: payment_params.clone(),
1477+
final_value_msat: 0,
1478+
final_cltv_expiry_delta: 0,
1479+
};
1480+
let failed_scid = 42;
1481+
let route = Route {
1482+
paths: vec![vec![RouteHop {
1483+
pubkey: receiver_pk,
1484+
node_features: NodeFeatures::empty(),
1485+
short_channel_id: failed_scid,
1486+
channel_features: ChannelFeatures::empty(),
1487+
fee_msat: 0,
1488+
cltv_expiry_delta: 0,
1489+
}]],
1490+
payment_params: Some(payment_params),
1491+
};
1492+
router.expect_find_route(route_params.clone(), Ok(route.clone()));
1493+
let mut route_params_w_failed_scid = route_params.clone();
1494+
route_params_w_failed_scid.payment_params.previously_failed_channels.push(failed_scid);
1495+
router.expect_find_route(route_params_w_failed_scid, Ok(route.clone()));
1496+
router.expect_find_route(route_params.clone(), Ok(route.clone()));
1497+
router.expect_find_route(route_params.clone(), Ok(route.clone()));
1498+
1499+
// Ensure that a ChannelUnavailable error will result in blaming an scid in the
1500+
// PaymentPathFailed event.
1501+
let pending_events = Mutex::new(Vec::new());
1502+
outbound_payments.send_payment(
1503+
PaymentHash([0; 32]), &None, PaymentId([0; 32]), Retry::Attempts(0), route_params.clone(),
1504+
&&router, vec![], || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger,
1505+
&pending_events,
1506+
|_, _, _, _, _, _, _, _, _| Err(APIError::ChannelUnavailable { err: "test".to_owned() }))
1507+
.unwrap();
1508+
let mut events = pending_events.lock().unwrap();
1509+
assert_eq!(events.len(), 2);
1510+
if let Event::PaymentPathFailed {
1511+
short_channel_id,
1512+
failure: PathFailure::InitialSend { err: APIError::ChannelUnavailable { .. }}, .. } = events[0]
1513+
{
1514+
assert_eq!(short_channel_id, Some(failed_scid));
1515+
} else { panic!("Unexpected event"); }
1516+
if let Event::PaymentFailed { .. } = events[1] { } else { panic!("Unexpected event"); }
1517+
events.clear();
1518+
core::mem::drop(events);
1519+
1520+
// Ensure that a MonitorUpdateInProgress "error" will not result in a PaymentPathFailed event.
1521+
outbound_payments.send_payment(
1522+
PaymentHash([0; 32]), &None, PaymentId([0; 32]), Retry::Attempts(0), route_params.clone(),
1523+
&&router, vec![], || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger,
1524+
&pending_events, |_, _, _, _, _, _, _, _, _| Err(APIError::MonitorUpdateInProgress))
1525+
.unwrap();
1526+
{
1527+
let events = pending_events.lock().unwrap();
1528+
assert_eq!(events.len(), 0);
1529+
}
1530+
1531+
// Ensure that any other error will result in a PaymentPathFailed event but no blamed scid.
1532+
outbound_payments.send_payment(
1533+
PaymentHash([0; 32]), &None, PaymentId([1; 32]), Retry::Attempts(0), route_params.clone(),
1534+
&&router, vec![], || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger,
1535+
&pending_events,
1536+
|_, _, _, _, _, _, _, _, _| Err(APIError::APIMisuseError { err: "test".to_owned() }))
1537+
.unwrap();
1538+
let events = pending_events.lock().unwrap();
1539+
assert_eq!(events.len(), 2);
1540+
if let Event::PaymentPathFailed {
1541+
short_channel_id,
1542+
failure: PathFailure::InitialSend { err: APIError::APIMisuseError { .. }}, .. } = events[0]
1543+
{
1544+
assert_eq!(short_channel_id, None);
1545+
} else { panic!("Unexpected event"); }
1546+
if let Event::PaymentFailed { .. } = events[1] { } else { panic!("Unexpected event"); }
1547+
}
14581548
}

0 commit comments

Comments
 (0)