@@ -485,7 +485,7 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
485485 /// The session_priv bytes of outbound payments which are pending resolution.
486486 /// The authoritative state of these HTLCs resides either within Channels or ChannelMonitors
487487 /// (if the channel has been force-closed), however we track them here to prevent duplicative
488- /// PaymentSent/PaymentFailed events. Specifically, in the case of a duplicative
488+ /// PaymentSent/MPPFragmentFailed/ PaymentFailed events. Specifically, in the case of a duplicative
489489 /// update_fulfill_htlc message after a reconnect, we may "claim" a payment twice.
490490 /// Additionally, because ChannelMonitors are often not re-serialized after connecting block(s)
491491 /// which may generate a claim event, we may receive similar duplicate claim/fail MonitorEvents
@@ -2837,25 +2837,35 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
28372837 self . fail_htlc_backwards_internal ( channel_state,
28382838 htlc_src, & payment_hash, HTLCFailReason :: Reason { failure_code, data : onion_failure_data} ) ;
28392839 } ,
2840- HTLCSource :: OutboundRoute { session_priv, mpp_id, .. } => {
2840+ HTLCSource :: OutboundRoute { session_priv, mpp_id, path , .. } => {
28412841 let mut session_priv_bytes = [ 0 ; 32 ] ;
28422842 session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
28432843 let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
28442844 if let hash_map:: Entry :: Occupied ( mut sessions) = outbounds. entry ( mpp_id) {
28452845 if sessions. get_mut ( ) . remove ( & session_priv_bytes) {
2846- self . pending_events . lock ( ) . unwrap ( ) . push (
2847- events:: Event :: PaymentFailed {
2848- payment_hash,
2849- rejected_by_dest : false ,
2850- network_update : None ,
2851- #[ cfg( test) ]
2852- error_code : None ,
2853- #[ cfg( test) ]
2854- error_data : None ,
2846+ match sessions. get ( ) . len ( ) {
2847+ 0 => {
2848+ self . pending_events . lock ( ) . unwrap ( ) . push (
2849+ events:: Event :: PaymentFailed {
2850+ payment_hash,
2851+ rejected_by_dest : false ,
2852+ network_update : None ,
2853+ #[ cfg( test) ]
2854+ error_code : None ,
2855+ #[ cfg( test) ]
2856+ error_data : None ,
2857+ }
2858+ ) ;
2859+ sessions. remove ( ) ;
2860+ } ,
2861+ _ => {
2862+ self . pending_events . lock ( ) . unwrap ( ) . push (
2863+ events:: Event :: MPPFragmentFailed {
2864+ payment_hash,
2865+ payment_path : path. clone ( )
2866+ }
2867+ ) ;
28552868 }
2856- ) ;
2857- if sessions. get ( ) . len ( ) == 0 {
2858- sessions. remove ( ) ;
28592869 }
28602870 }
28612871 } else {
@@ -2886,12 +2896,14 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
28862896 let mut session_priv_bytes = [ 0 ; 32 ] ;
28872897 session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
28882898 let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
2899+ let mut partial_failure = true ;
28892900 if let hash_map:: Entry :: Occupied ( mut sessions) = outbounds. entry ( mpp_id) {
28902901 if !sessions. get_mut ( ) . remove ( & session_priv_bytes) {
28912902 log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
28922903 return ;
28932904 }
28942905 if sessions. get ( ) . len ( ) == 0 {
2906+ partial_failure = false ;
28952907 sessions. remove ( ) ;
28962908 }
28972909 } else {
@@ -2909,42 +2921,60 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
29092921 // TODO: If we decided to blame ourselves (or one of our channels) in
29102922 // process_onion_failure we should close that channel as it implies our
29112923 // next-hop is needlessly blaming us!
2912- self . pending_events . lock ( ) . unwrap ( ) . push (
2913- events:: Event :: PaymentFailed {
2914- payment_hash : payment_hash. clone ( ) ,
2915- rejected_by_dest : !payment_retryable,
2916- network_update,
2917- #[ cfg( test) ]
2918- error_code : onion_error_code,
2919- #[ cfg( test) ]
2920- error_data : onion_error_data
2921- }
2922- ) ;
2924+ if partial_failure {
2925+ self . pending_events . lock ( ) . unwrap ( ) . push (
2926+ events:: Event :: MPPFragmentFailed {
2927+ payment_hash : payment_hash. clone ( ) ,
2928+ payment_path : path. clone ( )
2929+ }
2930+ ) ;
2931+ } else {
2932+ self . pending_events . lock ( ) . unwrap ( ) . push (
2933+ events:: Event :: PaymentFailed {
2934+ payment_hash : payment_hash. clone ( ) ,
2935+ rejected_by_dest : !payment_retryable,
2936+ network_update,
2937+ #[ cfg( test) ]
2938+ error_code : onion_error_code,
2939+ #[ cfg( test) ]
2940+ error_data : onion_error_data
2941+ }
2942+ ) ;
2943+ }
29232944 } ,
29242945 & HTLCFailReason :: Reason {
2925- #[ cfg( test) ]
2926- ref failure_code,
2927- #[ cfg( test) ]
2928- ref data,
2929- .. } => {
2930- // we get a fail_malformed_htlc from the first hop
2931- // TODO: We'd like to generate a NetworkUpdate for temporary
2932- // failures here, but that would be insufficient as get_route
2933- // generally ignores its view of our own channels as we provide them via
2934- // ChannelDetails.
2935- // TODO: For non-temporary failures, we really should be closing the
2936- // channel here as we apparently can't relay through them anyway.
2937- self . pending_events . lock ( ) . unwrap ( ) . push (
2938- events:: Event :: PaymentFailed {
2939- payment_hash : payment_hash. clone ( ) ,
2940- rejected_by_dest : path. len ( ) == 1 ,
2941- network_update : None ,
2942- #[ cfg( test) ]
2943- error_code : Some ( * failure_code) ,
2944- #[ cfg( test) ]
2945- error_data : Some ( data. clone ( ) ) ,
2946- }
2947- ) ;
2946+ #[ cfg( test) ]
2947+ ref failure_code,
2948+ #[ cfg( test) ]
2949+ ref data,
2950+ .. } => {
2951+ if partial_failure {
2952+ self . pending_events . lock ( ) . unwrap ( ) . push (
2953+ events:: Event :: MPPFragmentFailed {
2954+ payment_hash : payment_hash. clone ( ) ,
2955+ payment_path : path. clone ( )
2956+ }
2957+ ) ;
2958+ } else {
2959+ // we get a fail_malformed_htlc from the first hop
2960+ // TODO: We'd like to generate a PaymentFailureNetworkUpdate for temporary
2961+ // failures here, but that would be insufficient as get_route
2962+ // generally ignores its view of our own channels as we provide them via
2963+ // ChannelDetails.
2964+ // TODO: For non-temporary failures, we really should be closing the
2965+ // channel here as we apparently can't relay through them anyway.
2966+ self . pending_events . lock ( ) . unwrap ( ) . push (
2967+ events:: Event :: PaymentFailed {
2968+ payment_hash : payment_hash. clone ( ) ,
2969+ rejected_by_dest : path. len ( ) == 1 ,
2970+ network_update : None ,
2971+ #[ cfg( test) ]
2972+ error_code : Some ( * failure_code) ,
2973+ #[ cfg( test) ]
2974+ error_data : Some ( data. clone ( ) ) ,
2975+ }
2976+ ) ;
2977+ }
29482978 }
29492979 }
29502980 } ,
0 commit comments