@@ -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,24 +2837,34 @@ 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 Some ( sessions) = outbounds. get_mut ( & mpp_id) {
28452845 if sessions. remove ( & session_priv_bytes) {
2846- self . pending_events . lock ( ) . unwrap ( ) . push (
2847- events:: Event :: PaymentFailed {
2848- payment_hash,
2849- rejected_by_dest : false ,
2850- #[ cfg( test) ]
2851- error_code : None ,
2852- #[ cfg( test) ]
2853- error_data : None ,
2846+ match sessions. len ( ) {
2847+ 0 => {
2848+ self . pending_events . lock ( ) . unwrap ( ) . push (
2849+ events:: Event :: PaymentFailed {
2850+ payment_hash,
2851+ rejected_by_dest : false ,
2852+ #[ cfg( test) ]
2853+ error_code : None ,
2854+ #[ cfg( test) ]
2855+ error_data : None ,
2856+ }
2857+ ) ;
2858+ outbounds. remove ( & mpp_id) ;
2859+ } ,
2860+ _ => {
2861+ self . pending_events . lock ( ) . unwrap ( ) . push (
2862+ events:: Event :: MPPFragmentFailed {
2863+ payment_hash,
2864+ payment_path : path. clone ( )
2865+ }
2866+ ) ;
28542867 }
2855- ) ;
2856- if sessions. len ( ) == 0 {
2857- outbounds. remove ( & mpp_id) ;
28582868 }
28592869 continue
28602870 }
@@ -2885,12 +2895,14 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
28852895 let mut session_priv_bytes = [ 0 ; 32 ] ;
28862896 session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
28872897 let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
2898+ let mut partial_failure = true ;
28882899 if let Some ( sessions) = outbounds. get_mut ( & mpp_id) {
28892900 if !sessions. remove ( & session_priv_bytes) {
28902901 log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
28912902 return ;
28922903 }
28932904 if sessions. len ( ) == 0 {
2905+ partial_failure = false ;
28942906 outbounds. remove ( & mpp_id) ;
28952907 }
28962908 } else {
@@ -2915,40 +2927,58 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
29152927 }
29162928 ) ;
29172929 }
2918- self . pending_events . lock ( ) . unwrap ( ) . push (
2919- events:: Event :: PaymentFailed {
2920- payment_hash : payment_hash. clone ( ) ,
2921- rejected_by_dest : !payment_retryable,
2922- #[ cfg( test) ]
2923- error_code : onion_error_code,
2924- #[ cfg( test) ]
2925- error_data : onion_error_data
2926- }
2927- ) ;
2930+ if partial_failure {
2931+ self . pending_events . lock ( ) . unwrap ( ) . push (
2932+ events:: Event :: MPPFragmentFailed {
2933+ payment_hash : payment_hash. clone ( ) ,
2934+ payment_path : path. clone ( )
2935+ }
2936+ ) ;
2937+ } else {
2938+ self . pending_events . lock ( ) . unwrap ( ) . push (
2939+ events:: Event :: PaymentFailed {
2940+ payment_hash : payment_hash. clone ( ) ,
2941+ rejected_by_dest : !payment_retryable,
2942+ #[ cfg( test) ]
2943+ error_code : onion_error_code,
2944+ #[ cfg( test) ]
2945+ error_data : onion_error_data
2946+ }
2947+ ) ;
2948+ }
29282949 } ,
29292950 & HTLCFailReason :: Reason {
2930- #[ cfg( test) ]
2931- ref failure_code,
2932- #[ cfg( test) ]
2933- ref data,
2934- .. } => {
2935- // we get a fail_malformed_htlc from the first hop
2936- // TODO: We'd like to generate a PaymentFailureNetworkUpdate for temporary
2937- // failures here, but that would be insufficient as get_route
2938- // generally ignores its view of our own channels as we provide them via
2939- // ChannelDetails.
2940- // TODO: For non-temporary failures, we really should be closing the
2941- // channel here as we apparently can't relay through them anyway.
2942- self . pending_events . lock ( ) . unwrap ( ) . push (
2943- events:: Event :: PaymentFailed {
2944- payment_hash : payment_hash. clone ( ) ,
2945- rejected_by_dest : path. len ( ) == 1 ,
2946- #[ cfg( test) ]
2947- error_code : Some ( * failure_code) ,
2948- #[ cfg( test) ]
2949- error_data : Some ( data. clone ( ) ) ,
2950- }
2951- ) ;
2951+ #[ cfg( test) ]
2952+ ref failure_code,
2953+ #[ cfg( test) ]
2954+ ref data,
2955+ .. } => {
2956+ if partial_failure {
2957+ self . pending_events . lock ( ) . unwrap ( ) . push (
2958+ events:: Event :: MPPFragmentFailed {
2959+ payment_hash : payment_hash. clone ( ) ,
2960+ payment_path : path. clone ( )
2961+ }
2962+ ) ;
2963+ } else {
2964+ // we get a fail_malformed_htlc from the first hop
2965+ // TODO: We'd like to generate a PaymentFailureNetworkUpdate for temporary
2966+ // failures here, but that would be insufficient as get_route
2967+ // generally ignores its view of our own channels as we provide them via
2968+ // ChannelDetails.
2969+ // TODO: For non-temporary failures, we really should be closing the
2970+ // channel here as we apparently can't relay through them anyway.
2971+ self . pending_events . lock ( ) . unwrap ( ) . push (
2972+ events:: Event :: PaymentFailed {
2973+ payment_hash : payment_hash. clone ( ) ,
2974+ rejected_by_dest : path. len ( ) == 1 ,
2975+ #[ cfg( test) ]
2976+ error_code : Some ( * failure_code) ,
2977+ #[ cfg( test) ]
2978+ error_data : Some ( data. clone ( ) ) ,
2979+ }
2980+ ) ;
2981+ }
29522982 }
29532983 }
29542984 } ,
0 commit comments