@@ -811,7 +811,7 @@ impl OutboundPayments {
811811 {
812812 let onion_session_privs = self . add_new_pending_payment ( payment_hash, recipient_onion. clone ( ) , payment_id, None , route, None , None , entropy_source, best_block_height) ?;
813813 self . pay_route_internal ( route, payment_hash, & recipient_onion, None , None , payment_id, None ,
814- onion_session_privs, node_signer, best_block_height, & send_payment_along_path)
814+ & onion_session_privs, node_signer, best_block_height, & send_payment_along_path)
815815 . map_err ( |e| { self . remove_outbound_if_all_failed ( payment_id, & e) ; e } )
816816 }
817817
@@ -991,7 +991,7 @@ impl OutboundPayments {
991991
992992 let result = self . pay_route_internal (
993993 & route, payment_hash, & recipient_onion, keysend_preimage, invoice_request, payment_id,
994- Some ( route_params. final_value_msat ) , onion_session_privs, node_signer, best_block_height,
994+ Some ( route_params. final_value_msat ) , & onion_session_privs, node_signer, best_block_height,
995995 & send_payment_along_path
996996 ) ;
997997 log_info ! (
@@ -1000,9 +1000,9 @@ impl OutboundPayments {
10001000 ) ;
10011001 if let Err ( e) = result {
10021002 self . handle_pay_route_err (
1003- e, payment_id, payment_hash, route, route_params, router, first_hops,
1004- & inflight_htlcs, entropy_source, node_signer, best_block_height, logger,
1005- pending_events , & send_payment_along_path
1003+ e, payment_id, payment_hash, route, route_params, onion_session_privs , router, first_hops,
1004+ & inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events ,
1005+ & send_payment_along_path
10061006 ) ;
10071007 }
10081008 Ok ( ( ) )
@@ -1276,12 +1276,16 @@ impl OutboundPayments {
12761276 } ) ?;
12771277
12781278 let res = self . pay_route_internal ( & route, payment_hash, & recipient_onion,
1279- keysend_preimage, None , payment_id, None , onion_session_privs, node_signer,
1279+ keysend_preimage, None , payment_id, None , & onion_session_privs, node_signer,
12801280 best_block_height, & send_payment_along_path) ;
12811281 log_info ! ( logger, "Sending payment with id {} and hash {} returned {:?}" ,
12821282 payment_id, payment_hash, res) ;
12831283 if let Err ( e) = res {
1284- self . handle_pay_route_err ( e, payment_id, payment_hash, route, route_params, router, first_hops, & inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, & send_payment_along_path) ;
1284+ self . handle_pay_route_err (
1285+ e, payment_id, payment_hash, route, route_params, onion_session_privs, router, first_hops,
1286+ & inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events,
1287+ & send_payment_along_path
1288+ ) ;
12851289 }
12861290 Ok ( ( ) )
12871291 }
@@ -1433,19 +1437,25 @@ impl OutboundPayments {
14331437 }
14341438 } ;
14351439 let res = self . pay_route_internal ( & route, payment_hash, & recipient_onion, keysend_preimage,
1436- invoice_request. as_ref ( ) , payment_id, Some ( total_msat) , onion_session_privs, node_signer,
1440+ invoice_request. as_ref ( ) , payment_id, Some ( total_msat) , & onion_session_privs, node_signer,
14371441 best_block_height, & send_payment_along_path) ;
14381442 log_info ! ( logger, "Result retrying payment id {}: {:?}" , & payment_id, res) ;
14391443 if let Err ( e) = res {
1440- self . handle_pay_route_err ( e, payment_id, payment_hash, route, route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path) ;
1444+ self . handle_pay_route_err (
1445+ e, payment_id, payment_hash, route, route_params, onion_session_privs, router, first_hops,
1446+ inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events,
1447+ send_payment_along_path
1448+ ) ;
14411449 }
14421450 }
14431451
14441452 fn handle_pay_route_err < R : Deref , NS : Deref , ES : Deref , IH , SP , L : Deref > (
14451453 & self , err : PaymentSendFailure , payment_id : PaymentId , payment_hash : PaymentHash , route : Route ,
1446- mut route_params : RouteParameters , router : & R , first_hops : Vec < ChannelDetails > ,
1447- inflight_htlcs : & IH , entropy_source : & ES , node_signer : & NS , best_block_height : u32 , logger : & L ,
1448- pending_events : & Mutex < VecDeque < ( events:: Event , Option < EventCompletionAction > ) > > , send_payment_along_path : & SP ,
1454+ mut route_params : RouteParameters , onion_session_privs : Vec < [ u8 ; 32 ] > , router : & R ,
1455+ first_hops : Vec < ChannelDetails > , inflight_htlcs : & IH , entropy_source : & ES , node_signer : & NS ,
1456+ best_block_height : u32 , logger : & L ,
1457+ pending_events : & Mutex < VecDeque < ( events:: Event , Option < EventCompletionAction > ) > > ,
1458+ send_payment_along_path : & SP ,
14491459 )
14501460 where
14511461 R :: Target : Router ,
@@ -1457,10 +1467,24 @@ impl OutboundPayments {
14571467 {
14581468 match err {
14591469 PaymentSendFailure :: AllFailedResendSafe ( errs) => {
1470+ self . remove_session_privs ( payment_id, route. paths . iter ( ) . zip ( onion_session_privs. iter ( ) ) ) ;
14601471 Self :: push_path_failed_evs_and_scids ( payment_id, payment_hash, & mut route_params, route. paths , errs. into_iter ( ) . map ( |e| Err ( e) ) , logger, pending_events) ;
14611472 self . find_route_and_send_payment ( payment_hash, payment_id, route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path) ;
14621473 } ,
14631474 PaymentSendFailure :: PartialFailure { failed_paths_retry : Some ( mut retry) , results, .. } => {
1475+ debug_assert_eq ! ( results. len( ) , route. paths. len( ) ) ;
1476+ debug_assert_eq ! ( results. len( ) , onion_session_privs. len( ) ) ;
1477+ let failed_paths = results. iter ( ) . zip ( route. paths . iter ( ) . zip ( onion_session_privs. iter ( ) ) )
1478+ . filter_map ( |( path_res, ( path, session_priv) ) | {
1479+ match path_res {
1480+ // While a MonitorUpdateInProgress is an Err(_), the payment is still
1481+ // considered "in flight" and we shouldn't remove it from the
1482+ // PendingOutboundPayment set.
1483+ Ok ( _) | Err ( APIError :: MonitorUpdateInProgress ) => None ,
1484+ _ => Some ( ( path, session_priv) )
1485+ }
1486+ } ) ;
1487+ self . remove_session_privs ( payment_id, failed_paths) ;
14641488 Self :: push_path_failed_evs_and_scids ( payment_id, payment_hash, & mut retry, route. paths , results. into_iter ( ) , logger, pending_events) ;
14651489 // Some paths were sent, even if we failed to send the full MPP value our recipient may
14661490 // misbehave and claim the funds, at which point we have to consider the payment sent, so
@@ -1474,11 +1498,13 @@ impl OutboundPayments {
14741498 } ,
14751499 PaymentSendFailure :: PathParameterError ( results) => {
14761500 log_error ! ( logger, "Failed to send to route due to parameter error in a single path. Your router is buggy" ) ;
1501+ self . remove_session_privs ( payment_id, route. paths . iter ( ) . zip ( onion_session_privs. iter ( ) ) ) ;
14771502 Self :: push_path_failed_evs_and_scids ( payment_id, payment_hash, & mut route_params, route. paths , results. into_iter ( ) , logger, pending_events) ;
14781503 self . abandon_payment ( payment_id, PaymentFailureReason :: UnexpectedError , pending_events) ;
14791504 } ,
14801505 PaymentSendFailure :: ParameterError ( e) => {
14811506 log_error ! ( logger, "Failed to send to route due to parameter error: {:?}. Your router is buggy" , e) ;
1507+ self . remove_session_privs ( payment_id, route. paths . iter ( ) . zip ( onion_session_privs. iter ( ) ) ) ;
14821508 self . abandon_payment ( payment_id, PaymentFailureReason :: UnexpectedError , pending_events) ;
14831509 } ,
14841510 PaymentSendFailure :: DuplicatePayment => debug_assert ! ( false ) , // unreachable
@@ -1518,6 +1544,21 @@ impl OutboundPayments {
15181544 }
15191545 }
15201546
1547+ // If a payment fails after adding the pending payment but before any HTLCs are locked into
1548+ // channels, we need to clear the session_privs in order for abandoning the payment to succeed.
1549+ fn remove_session_privs < ' a , I : Iterator < Item = ( & ' a Path , & ' a [ u8 ; 32 ] ) > > (
1550+ & self , payment_id : PaymentId , path_session_priv : I
1551+ ) {
1552+ if let Some ( payment) = self . pending_outbound_payments . lock ( ) . unwrap ( ) . get_mut ( & payment_id) {
1553+ for ( path, session_priv_bytes) in path_session_priv {
1554+ let removed = payment. remove ( session_priv_bytes, Some ( path) ) ;
1555+ debug_assert ! ( removed, "This can't happen as the payment has an entry for this path added by callers" ) ;
1556+ }
1557+ } else {
1558+ debug_assert ! ( false , "This can't happen as the payment was added by callers" ) ;
1559+ }
1560+ }
1561+
15211562 pub ( super ) fn send_probe < ES : Deref , NS : Deref , F > (
15221563 & self , path : Path , probing_cookie_secret : [ u8 ; 32 ] , entropy_source : & ES , node_signer : & NS ,
15231564 best_block_height : u32 , send_payment_along_path : F
@@ -1549,7 +1590,7 @@ impl OutboundPayments {
15491590
15501591 let recipient_onion_fields = RecipientOnionFields :: spontaneous_empty ( ) ;
15511592 match self . pay_route_internal ( & route, payment_hash, & recipient_onion_fields,
1552- None , None , payment_id, None , onion_session_privs, node_signer, best_block_height,
1593+ None , None , payment_id, None , & onion_session_privs, node_signer, best_block_height,
15531594 & send_payment_along_path
15541595 ) {
15551596 Ok ( ( ) ) => Ok ( ( payment_hash, payment_id) ) ,
@@ -1740,7 +1781,7 @@ impl OutboundPayments {
17401781 fn pay_route_internal < NS : Deref , F > (
17411782 & self , route : & Route , payment_hash : PaymentHash , recipient_onion : & RecipientOnionFields ,
17421783 keysend_preimage : Option < PaymentPreimage > , invoice_request : Option < & InvoiceRequest > ,
1743- payment_id : PaymentId , recv_value_msat : Option < u64 > , onion_session_privs : Vec < [ u8 ; 32 ] > ,
1784+ payment_id : PaymentId , recv_value_msat : Option < u64 > , onion_session_privs : & Vec < [ u8 ; 32 ] > ,
17441785 node_signer : & NS , best_block_height : u32 , send_payment_along_path : & F
17451786 ) -> Result < ( ) , PaymentSendFailure >
17461787 where
@@ -1791,30 +1832,12 @@ impl OutboundPayments {
17911832 let cur_height = best_block_height + 1 ;
17921833 let mut results = Vec :: new ( ) ;
17931834 debug_assert_eq ! ( route. paths. len( ) , onion_session_privs. len( ) ) ;
1794- for ( path, session_priv_bytes) in route. paths . iter ( ) . zip ( onion_session_privs. into_iter ( ) ) {
1795- let mut path_res = send_payment_along_path ( SendAlongPathArgs {
1835+ for ( path, session_priv_bytes) in route. paths . iter ( ) . zip ( onion_session_privs. iter ( ) ) {
1836+ let path_res = send_payment_along_path ( SendAlongPathArgs {
17961837 path : & path, payment_hash : & payment_hash, recipient_onion, total_value,
17971838 cur_height, payment_id, keysend_preimage : & keysend_preimage, invoice_request,
1798- session_priv_bytes
1839+ session_priv_bytes : * session_priv_bytes
17991840 } ) ;
1800- match path_res {
1801- Ok ( _) => { } ,
1802- Err ( APIError :: MonitorUpdateInProgress ) => {
1803- // While a MonitorUpdateInProgress is an Err(_), the payment is still
1804- // considered "in flight" and we shouldn't remove it from the
1805- // PendingOutboundPayment set.
1806- } ,
1807- Err ( _) => {
1808- let mut pending_outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
1809- if let Some ( payment) = pending_outbounds. get_mut ( & payment_id) {
1810- let removed = payment. remove ( & session_priv_bytes, Some ( path) ) ;
1811- debug_assert ! ( removed, "This can't happen as the payment has an entry for this path added by callers" ) ;
1812- } else {
1813- debug_assert ! ( false , "This can't happen as the payment was added by callers" ) ;
1814- path_res = Err ( APIError :: APIMisuseError { err : "Internal error: payment disappeared during processing. Please report this bug!" . to_owned ( ) } ) ;
1815- }
1816- }
1817- }
18181841 results. push ( path_res) ;
18191842 }
18201843 let mut has_ok = false ;
@@ -1879,17 +1902,23 @@ impl OutboundPayments {
18791902 F : Fn ( SendAlongPathArgs ) -> Result < ( ) , APIError > ,
18801903 {
18811904 self . pay_route_internal ( route, payment_hash, & recipient_onion,
1882- keysend_preimage, None , payment_id, recv_value_msat, onion_session_privs,
1905+ keysend_preimage, None , payment_id, recv_value_msat, & onion_session_privs,
18831906 node_signer, best_block_height, & send_payment_along_path)
18841907 . map_err ( |e| { self . remove_outbound_if_all_failed ( payment_id, & e) ; e } )
18851908 }
18861909
18871910 // If we failed to send any paths, remove the new PaymentId from the `pending_outbound_payments`
18881911 // map as the payment is free to be resent.
18891912 fn remove_outbound_if_all_failed ( & self , payment_id : PaymentId , err : & PaymentSendFailure ) {
1890- if let & PaymentSendFailure :: AllFailedResendSafe ( _) = err {
1891- let removed = self . pending_outbound_payments . lock ( ) . unwrap ( ) . remove ( & payment_id) . is_some ( ) ;
1892- debug_assert ! ( removed, "We should always have a pending payment to remove here" ) ;
1913+ match err {
1914+ PaymentSendFailure :: AllFailedResendSafe ( _)
1915+ | PaymentSendFailure :: ParameterError ( _)
1916+ | PaymentSendFailure :: PathParameterError ( _) =>
1917+ {
1918+ let removed = self . pending_outbound_payments . lock ( ) . unwrap ( ) . remove ( & payment_id) . is_some ( ) ;
1919+ debug_assert ! ( removed, "We should always have a pending payment to remove here" ) ;
1920+ } ,
1921+ PaymentSendFailure :: DuplicatePayment | PaymentSendFailure :: PartialFailure { .. } => { }
18931922 }
18941923 }
18951924
0 commit comments