@@ -485,7 +485,7 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
485
485
/// The session_priv bytes of outbound payments which are pending resolution.
486
486
/// The authoritative state of these HTLCs resides either within Channels or ChannelMonitors
487
487
/// (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
489
489
/// update_fulfill_htlc message after a reconnect, we may "claim" a payment twice.
490
490
/// Additionally, because ChannelMonitors are often not re-serialized after connecting block(s)
491
491
/// 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
2837
2837
self . fail_htlc_backwards_internal ( channel_state,
2838
2838
htlc_src, & payment_hash, HTLCFailReason :: Reason { failure_code, data : onion_failure_data} ) ;
2839
2839
} ,
2840
- HTLCSource :: OutboundRoute { session_priv, mpp_id, .. } => {
2840
+ HTLCSource :: OutboundRoute { session_priv, mpp_id, path , .. } => {
2841
2841
let mut session_priv_bytes = [ 0 ; 32 ] ;
2842
2842
session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
2843
2843
let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
2844
2844
if let Some ( sessions) = outbounds. get_mut ( & mpp_id) {
2845
2845
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
+ ) ;
2854
2867
}
2855
- ) ;
2856
- if sessions. len ( ) == 0 {
2857
- outbounds. remove ( & mpp_id) ;
2858
2868
}
2859
2869
continue
2860
2870
}
@@ -2885,12 +2895,14 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2885
2895
let mut session_priv_bytes = [ 0 ; 32 ] ;
2886
2896
session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
2887
2897
let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
2898
+ let mut partial_failure = true ;
2888
2899
if let Some ( sessions) = outbounds. get_mut ( & mpp_id) {
2889
2900
if !sessions. remove ( & session_priv_bytes) {
2890
2901
log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
2891
2902
return ;
2892
2903
}
2893
2904
if sessions. len ( ) == 0 {
2905
+ partial_failure = false ;
2894
2906
outbounds. remove ( & mpp_id) ;
2895
2907
}
2896
2908
} else {
@@ -2915,40 +2927,58 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2915
2927
}
2916
2928
) ;
2917
2929
}
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
+ }
2928
2949
} ,
2929
2950
& 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
+ }
2952
2982
}
2953
2983
}
2954
2984
} ,
0 commit comments