Skip to content

Commit a103cc1

Browse files
Test ChannelManager automatic retries
1 parent 3213f44 commit a103cc1

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

0 commit comments

Comments
 (0)