@@ -489,7 +489,8 @@ impl OutboundPayments {
489489
490490 pub ( super ) fn check_retry_payments < R : Deref , ES : Deref , NS : Deref , SP , IH , FH , L : Deref > (
491491 & self , router : & R , first_hops : FH , inflight_htlcs : IH , entropy_source : & ES , node_signer : & NS ,
492- best_block_height : u32 , logger : & L , send_payment_along_path : SP ,
492+ best_block_height : u32 , pending_events : & Mutex < Vec < events:: Event > > , logger : & L ,
493+ send_payment_along_path : SP ,
493494 )
494495 where
495496 R :: Target : Router ,
@@ -523,10 +524,14 @@ impl OutboundPayments {
523524 }
524525 }
525526 }
527+ core:: mem:: drop ( outbounds) ;
526528 if let Some ( ( payment_id, route_params) ) = retry_id_route_params {
527- core:: mem:: drop ( outbounds) ;
528529 if let Err ( e) = self . pay_internal ( payment_id, None , route_params, router, first_hops ( ) , inflight_htlcs ( ) , entropy_source, node_signer, best_block_height, logger, & send_payment_along_path) {
529530 log_info ! ( logger, "Errored retrying payment: {:?}" , e) ;
531+ // If we error on retry, there is no chance of the payment succeeding and no HTLCs have
532+ // been irrevocably committed to, so we can safely abandon. See docs on `pay_internal` for
533+ // more information.
534+ self . abandon_payment ( payment_id, pending_events) ;
530535 }
531536 } else { break }
532537 }
@@ -1205,18 +1210,19 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
12051210
12061211#[ cfg( test) ]
12071212mod tests {
1213+ use super :: * ;
12081214 use bitcoin:: blockdata:: constants:: genesis_block;
12091215 use bitcoin:: network:: constants:: Network ;
12101216 use bitcoin:: secp256k1:: { PublicKey , Secp256k1 , SecretKey } ;
12111217
12121218 use crate :: ln:: PaymentHash ;
12131219 use crate :: ln:: channelmanager:: { PaymentId , PaymentSendFailure } ;
12141220 use crate :: ln:: msgs:: { ErrorAction , LightningError } ;
1215- use crate :: ln:: outbound_payment:: { OutboundPayments , Retry } ;
12161221 use crate :: routing:: gossip:: NetworkGraph ;
12171222 use crate :: routing:: router:: { InFlightHtlcs , PaymentParameters , Route , RouteParameters } ;
12181223 use crate :: sync:: Arc ;
12191224 use crate :: util:: errors:: APIError ;
1225+ use crate :: util:: events:: Event ;
12201226 use crate :: util:: test_utils;
12211227
12221228 #[ test]
@@ -1301,4 +1307,54 @@ mod tests {
13011307 assert ! ( err. contains( "Failed to find a route" ) ) ;
13021308 } else { panic ! ( "Unexpected error" ) ; }
13031309 }
1310+
1311+ #[ test]
1312+ fn fail_on_retry_error ( ) {
1313+ let outbound_payments = OutboundPayments :: new ( ) ;
1314+ let logger = test_utils:: TestLogger :: new ( ) ;
1315+ let genesis_hash = genesis_block ( Network :: Testnet ) . header . block_hash ( ) ;
1316+ let network_graph = Arc :: new ( NetworkGraph :: new ( genesis_hash, & logger) ) ;
1317+ let router = test_utils:: TestRouter :: new ( network_graph) ;
1318+ let secp_ctx = Secp256k1 :: new ( ) ;
1319+ let session_priv = [ 42 ; 32 ] ;
1320+ let keys_manager = test_utils:: TestKeysInterface :: new ( & [ 0 ; 32 ] , Network :: Testnet ) ;
1321+ {
1322+ let mut random_bytes_override = keys_manager. override_random_bytes . lock ( ) . unwrap ( ) ;
1323+ * random_bytes_override = Some ( session_priv) ;
1324+ }
1325+
1326+ let payment_params = PaymentParameters :: from_node_id (
1327+ PublicKey :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ) , 0 ) ;
1328+ let route_params = RouteParameters {
1329+ payment_params,
1330+ final_value_msat : 1000 ,
1331+ final_cltv_expiry_delta : 0 ,
1332+ } ;
1333+ router. expect_find_route ( route_params. clone ( ) ,
1334+ Err ( LightningError { err : String :: new ( ) , action : ErrorAction :: IgnoreError } ) ) ;
1335+ let our_payment_id = PaymentId ( [ 0 ; 32 ] ) ;
1336+ let our_payment_hash = PaymentHash ( [ 0 ; 32 ] ) ;
1337+ outbound_payments. add_new_pending_payment ( our_payment_hash, None , our_payment_id, None ,
1338+ & Route { paths : vec ! [ ] , payment_params : None } , Some ( Retry :: Attempts ( 1 ) ) ,
1339+ Some ( route_params. payment_params . clone ( ) ) , & & keys_manager, 0 ) . unwrap ( ) ;
1340+ {
1341+ // Simulate that there are more sats that need to be sent that are pending.
1342+ let mut pending_outbounds = outbound_payments. pending_outbound_payments . lock ( ) . unwrap ( ) ;
1343+ if let Some ( PendingOutboundPayment :: Retryable { ref mut total_msat, .. } ) = pending_outbounds. get_mut ( & our_payment_id) {
1344+ * total_msat += 1000 ;
1345+ }
1346+ }
1347+
1348+ let pending_events_mtx = Mutex :: new ( vec ! [ ] ) ;
1349+ outbound_payments. check_retry_payments ( & & router, || vec ! [ ] , || InFlightHtlcs :: new ( ) , & & keys_manager, & & keys_manager, 0 , & pending_events_mtx, & & logger, |_, _, _, _, _, _, _, _, _| Ok ( ( ) ) ) ;
1350+ let pending_events = pending_events_mtx. lock ( ) . unwrap ( ) ;
1351+ assert_eq ! ( pending_events. len( ) , 1 ) ;
1352+ match pending_events[ 0 ] {
1353+ Event :: PaymentFailed { payment_id, payment_hash } => {
1354+ assert_eq ! ( payment_id, our_payment_id) ;
1355+ assert_eq ! ( payment_hash, our_payment_hash) ;
1356+ } ,
1357+ _ => panic ! ( )
1358+ }
1359+ }
13041360}
0 commit comments