Skip to content

Commit 3f0ab70

Browse files
Test ChannelManager automatic retries
1 parent 560711b commit 3f0ab70

File tree

3 files changed

+606
-2
lines changed

3 files changed

+606
-2
lines changed

lightning/src/ln/outbound_payment.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,3 +1123,99 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
11231123
(2, payment_hash, required),
11241124
},
11251125
);
1126+
1127+
#[cfg(test)]
1128+
mod tests {
1129+
use bitcoin::blockdata::constants::genesis_block;
1130+
use bitcoin::network::constants::Network;
1131+
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
1132+
1133+
use crate::ln::PaymentHash;
1134+
use crate::ln::channelmanager::{PaymentId, PaymentSendFailure};
1135+
use crate::ln::msgs::{ErrorAction, LightningError};
1136+
use crate::ln::outbound_payment::{OutboundPayments, Retry};
1137+
use crate::routing::gossip::NetworkGraph;
1138+
use crate::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteParameters};
1139+
use crate::sync::Arc;
1140+
use crate::util::errors::APIError;
1141+
use crate::util::test_utils;
1142+
1143+
#[test]
1144+
#[cfg(feature = "std")]
1145+
fn fails_paying_after_expiration() {
1146+
do_fails_paying_after_expiration(false);
1147+
do_fails_paying_after_expiration(true);
1148+
}
1149+
#[cfg(feature = "std")]
1150+
fn do_fails_paying_after_expiration(on_retry: bool) {
1151+
let outbound_payments = OutboundPayments::new();
1152+
let logger = test_utils::TestLogger::new();
1153+
let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
1154+
let network_graph = Arc::new(NetworkGraph::new(genesis_hash, &logger));
1155+
let router = test_utils::TestRouter::new(network_graph);
1156+
let secp_ctx = Secp256k1::new();
1157+
let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet);
1158+
1159+
let past_expiry_time = std::time::SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() - 2;
1160+
let payment_params = PaymentParameters::from_node_id(
1161+
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()))
1162+
.with_expiry_time(past_expiry_time);
1163+
let expired_route_params = RouteParameters {
1164+
payment_params,
1165+
final_value_msat: 0,
1166+
final_cltv_expiry_delta: 0,
1167+
};
1168+
let err = if on_retry {
1169+
outbound_payments.pay_internal(
1170+
PaymentId([0; 32]), None, expired_route_params, &&router, vec![], InFlightHtlcs::new(),
1171+
&&keys_manager, &&keys_manager, 0, &|_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err()
1172+
} else {
1173+
outbound_payments.send_payment(
1174+
PaymentHash([0; 32]), &None, PaymentId([0; 32]), Retry::Attempts(0), expired_route_params,
1175+
&&router, vec![], InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, |_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err()
1176+
};
1177+
if let PaymentSendFailure::ParameterError(APIError::APIMisuseError { err }) = err {
1178+
assert!(err.contains("Invoice expired"));
1179+
} else { panic!("Unexpected error"); }
1180+
}
1181+
1182+
#[test]
1183+
fn find_route_error() {
1184+
do_find_route_error(false);
1185+
do_find_route_error(true);
1186+
}
1187+
fn do_find_route_error(on_retry: bool) {
1188+
let outbound_payments = OutboundPayments::new();
1189+
let logger = test_utils::TestLogger::new();
1190+
let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
1191+
let network_graph = Arc::new(NetworkGraph::new(genesis_hash, &logger));
1192+
let router = test_utils::TestRouter::new(network_graph);
1193+
let secp_ctx = Secp256k1::new();
1194+
let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet);
1195+
1196+
router.expect_find_route(Err(LightningError { err: String::new(), action: ErrorAction::IgnoreError }));
1197+
1198+
let payment_params = PaymentParameters::from_node_id(
1199+
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()));
1200+
let route_params = RouteParameters {
1201+
payment_params,
1202+
final_value_msat: 0,
1203+
final_cltv_expiry_delta: 0,
1204+
};
1205+
let err = if on_retry {
1206+
outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), None, PaymentId([0; 32]),
1207+
&Route { paths: vec![], payment_params: None }, Retry::Attempts(1), Some(route_params.clone()),
1208+
&&keys_manager, 0).unwrap();
1209+
outbound_payments.pay_internal(
1210+
PaymentId([0; 32]), None, route_params, &&router, vec![], InFlightHtlcs::new(),
1211+
&&keys_manager, &&keys_manager, 0, &|_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err()
1212+
} else {
1213+
outbound_payments.send_payment(
1214+
PaymentHash([0; 32]), &None, PaymentId([0; 32]), Retry::Attempts(0), route_params,
1215+
&&router, vec![], InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, |_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err()
1216+
};
1217+
if let PaymentSendFailure::ParameterError(APIError::APIMisuseError { err }) = err {
1218+
assert!(err.contains("Failed to find a route"));
1219+
} else { panic!("Unexpected error"); }
1220+
}
1221+
}

0 commit comments

Comments
 (0)