Skip to content

Commit 2132629

Browse files
Test ChannelManager automatic retries
1 parent 6343bac commit 2132629

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

0 commit comments

Comments
 (0)