Skip to content

Commit 3c7b493

Browse files
Test ChannelManager automatic retries
1 parent d5a82c2 commit 3c7b493

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

0 commit comments

Comments
 (0)