@@ -489,7 +489,8 @@ impl OutboundPayments {
489
489
490
490
pub ( super ) fn check_retry_payments < R : Deref , ES : Deref , NS : Deref , SP , IH , FH , L : Deref > (
491
491
& 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 ,
493
494
)
494
495
where
495
496
R :: Target : Router ,
@@ -523,10 +524,13 @@ impl OutboundPayments {
523
524
}
524
525
}
525
526
}
527
+ core:: mem:: drop ( outbounds) ;
526
528
if let Some ( ( payment_id, route_params) ) = retry_id_route_params {
527
- core:: mem:: drop ( outbounds) ;
528
529
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) {
529
530
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.
533
+ self . abandon_payment ( payment_id, pending_events) ;
530
534
}
531
535
} else { break }
532
536
}
@@ -1192,18 +1196,19 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
1192
1196
1193
1197
#[ cfg( test) ]
1194
1198
mod tests {
1199
+ use super :: * ;
1195
1200
use bitcoin:: blockdata:: constants:: genesis_block;
1196
1201
use bitcoin:: network:: constants:: Network ;
1197
1202
use bitcoin:: secp256k1:: { PublicKey , Secp256k1 , SecretKey } ;
1198
1203
1199
1204
use crate :: ln:: PaymentHash ;
1200
1205
use crate :: ln:: channelmanager:: { PaymentId , PaymentSendFailure } ;
1201
1206
use crate :: ln:: msgs:: { ErrorAction , LightningError } ;
1202
- use crate :: ln:: outbound_payment:: { OutboundPayments , Retry } ;
1203
1207
use crate :: routing:: gossip:: NetworkGraph ;
1204
1208
use crate :: routing:: router:: { InFlightHtlcs , PaymentParameters , Route , RouteParameters } ;
1205
1209
use crate :: sync:: Arc ;
1206
1210
use crate :: util:: errors:: APIError ;
1211
+ use crate :: util:: events:: Event ;
1207
1212
use crate :: util:: test_utils;
1208
1213
1209
1214
#[ test]
@@ -1288,4 +1293,55 @@ mod tests {
1288
1293
assert ! ( err. contains( "Failed to find a route" ) ) ;
1289
1294
} else { panic ! ( "Unexpected error" ) ; }
1290
1295
}
1296
+
1297
+ #[ test]
1298
+ fn fail_on_retry_error ( ) {
1299
+ let outbound_payments = OutboundPayments :: new ( ) ;
1300
+ let logger = test_utils:: TestLogger :: new ( ) ;
1301
+ let genesis_hash = genesis_block ( Network :: Testnet ) . header . block_hash ( ) ;
1302
+ let network_graph = Arc :: new ( NetworkGraph :: new ( genesis_hash, & logger) ) ;
1303
+ let router = test_utils:: TestRouter :: new ( network_graph) ;
1304
+ let secp_ctx = Secp256k1 :: new ( ) ;
1305
+ let session_priv = [ 42 ; 32 ] ;
1306
+ let keys_manager = test_utils:: TestKeysInterface :: new ( & [ 0 ; 32 ] , Network :: Testnet ) ;
1307
+ {
1308
+ let mut random_bytes_override = keys_manager. override_random_bytes . lock ( ) . unwrap ( ) ;
1309
+ * random_bytes_override = Some ( session_priv) ;
1310
+ }
1311
+
1312
+ let payment_params = PaymentParameters :: from_node_id (
1313
+ PublicKey :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ) , 0 ) ;
1314
+ let route_params = RouteParameters {
1315
+ payment_params,
1316
+ final_value_msat : 1000 ,
1317
+ final_cltv_expiry_delta : 0 ,
1318
+ } ;
1319
+ router. expect_find_route ( route_params. clone ( ) ,
1320
+ Err ( LightningError { err : String :: new ( ) , action : ErrorAction :: IgnoreError } ) ) ;
1321
+ let our_payment_id = PaymentId ( [ 0 ; 32 ] ) ;
1322
+ let our_payment_hash = PaymentHash ( [ 0 ; 32 ] ) ;
1323
+ outbound_payments. add_new_pending_payment ( our_payment_hash, None , our_payment_id, None ,
1324
+ & Route { paths : vec ! [ ] , payment_params : None } , Some ( Retry :: Attempts ( 1 ) ) ,
1325
+ Some ( route_params. payment_params . clone ( ) ) , & & keys_manager, 0 ) . unwrap ( ) ;
1326
+ {
1327
+ // Simulate that there are more sats that need to be sent that are pending, so that
1328
+ // check_retry_payments flags it for retry.
1329
+ let mut pending_outbounds = outbound_payments. pending_outbound_payments . lock ( ) . unwrap ( ) ;
1330
+ if let Some ( PendingOutboundPayment :: Retryable { ref mut total_msat, .. } ) = pending_outbounds. get_mut ( & our_payment_id) {
1331
+ * total_msat += 1000 ;
1332
+ }
1333
+ }
1334
+
1335
+ let pending_events_mtx = Mutex :: new ( vec ! [ ] ) ;
1336
+ outbound_payments. check_retry_payments ( & & router, || vec ! [ ] , || InFlightHtlcs :: new ( ) , & & keys_manager, & & keys_manager, 0 , & pending_events_mtx, & & logger, |_, _, _, _, _, _, _, _, _| Ok ( ( ) ) ) ;
1337
+ let pending_events = pending_events_mtx. lock ( ) . unwrap ( ) ;
1338
+ assert_eq ! ( pending_events. len( ) , 1 ) ;
1339
+ match pending_events[ 0 ] {
1340
+ Event :: PaymentFailed { payment_id, payment_hash } => {
1341
+ assert_eq ! ( payment_id, our_payment_id) ;
1342
+ assert_eq ! ( payment_hash, our_payment_hash) ;
1343
+ } ,
1344
+ _ => panic ! ( )
1345
+ }
1346
+ }
1291
1347
}
0 commit comments