Skip to content

Commit cbea0a0

Browse files
Test ChannelManager automatic retries
1 parent 4045a41 commit cbea0a0

File tree

3 files changed

+601
-2
lines changed

3 files changed

+601
-2
lines changed

lightning/src/ln/outbound_payment.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,3 +1075,99 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
10751075
(2, payment_hash, required),
10761076
},
10771077
);
1078+
1079+
#[cfg(test)]
1080+
mod tests {
1081+
use bitcoin::blockdata::constants::genesis_block;
1082+
use bitcoin::network::constants::Network;
1083+
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
1084+
1085+
use crate::ln::PaymentHash;
1086+
use crate::ln::channelmanager::{PaymentId, PaymentSendFailure};
1087+
use crate::ln::msgs::{ErrorAction, LightningError};
1088+
use crate::ln::outbound_payment::{OutboundPayments, Retry};
1089+
use crate::routing::gossip::NetworkGraph;
1090+
use crate::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteParameters};
1091+
use crate::sync::Arc;
1092+
use crate::util::errors::APIError;
1093+
use crate::util::test_utils;
1094+
1095+
#[test]
1096+
#[cfg(feature = "std")]
1097+
fn fails_paying_after_expiration() {
1098+
do_fails_paying_after_expiration(false);
1099+
do_fails_paying_after_expiration(true);
1100+
}
1101+
#[cfg(feature = "std")]
1102+
fn do_fails_paying_after_expiration(on_retry: bool) {
1103+
let outbound_payments = OutboundPayments::new();
1104+
let logger = test_utils::TestLogger::new();
1105+
let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
1106+
let network_graph = Arc::new(NetworkGraph::new(genesis_hash, &logger));
1107+
let router = test_utils::TestRouter::new(network_graph);
1108+
let secp_ctx = Secp256k1::new();
1109+
let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet);
1110+
1111+
let past_expiry_time = std::time::SystemTime::UNIX_EPOCH.elapsed().unwrap().as_secs() - 2;
1112+
let payment_params = PaymentParameters::from_node_id(
1113+
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()))
1114+
.with_expiry_time(past_expiry_time);
1115+
let expired_route_params = RouteParameters {
1116+
payment_params,
1117+
final_value_msat: 0,
1118+
final_cltv_expiry_delta: 0,
1119+
};
1120+
let err = if on_retry {
1121+
outbound_payments.retry_payment(
1122+
PaymentId([0; 32]), expired_route_params, &&router, vec![], InFlightHtlcs::new(),
1123+
&&keys_manager, 0, &|_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err()
1124+
} else {
1125+
outbound_payments.send_payment(
1126+
PaymentHash([0; 32]), &None, PaymentId([0; 32]), Retry::Attempts(0), expired_route_params,
1127+
&&router, vec![], InFlightHtlcs::new(), &&keys_manager, 0, &&logger, |_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err()
1128+
};
1129+
if let PaymentSendFailure::ParameterError(APIError::APIMisuseError { err }) = err {
1130+
assert!(err.contains("Invoice expired"));
1131+
} else { panic!("Unexpected error"); }
1132+
}
1133+
1134+
#[test]
1135+
fn find_route_error() {
1136+
do_find_route_error(false);
1137+
do_find_route_error(true);
1138+
}
1139+
fn do_find_route_error(on_retry: bool) {
1140+
let outbound_payments = OutboundPayments::new();
1141+
let logger = test_utils::TestLogger::new();
1142+
let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
1143+
let network_graph = Arc::new(NetworkGraph::new(genesis_hash, &logger));
1144+
let router = test_utils::TestRouter::new(network_graph);
1145+
let secp_ctx = Secp256k1::new();
1146+
let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet);
1147+
1148+
router.expect_find_route(Err(LightningError { err: String::new(), action: ErrorAction::IgnoreError }));
1149+
1150+
let payment_params = PaymentParameters::from_node_id(
1151+
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()));
1152+
let route_params = RouteParameters {
1153+
payment_params,
1154+
final_value_msat: 0,
1155+
final_cltv_expiry_delta: 0,
1156+
};
1157+
let err = if on_retry {
1158+
outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), None, PaymentId([0; 32]),
1159+
&Route { paths: vec![], payment_params: None }, Retry::Attempts(1),
1160+
&&keys_manager, 0).unwrap();
1161+
outbound_payments.retry_payment(
1162+
PaymentId([0; 32]), route_params, &&router, vec![], InFlightHtlcs::new(),
1163+
&&keys_manager, 0, &|_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err()
1164+
} else {
1165+
outbound_payments.send_payment(
1166+
PaymentHash([0; 32]), &None, PaymentId([0; 32]), Retry::Attempts(0), route_params,
1167+
&&router, vec![], InFlightHtlcs::new(), &&keys_manager, 0, &&logger, |_, _, _, _, _, _, _, _, _| Ok(())).unwrap_err()
1168+
};
1169+
if let PaymentSendFailure::ParameterError(APIError::APIMisuseError { err }) = err {
1170+
assert!(err.contains("Failed to find a route"));
1171+
} else { panic!("Unexpected error"); }
1172+
}
1173+
}

0 commit comments

Comments
 (0)