@@ -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,25 +2837,35 @@ 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
- network_update : None ,
2851
- #[ cfg( test) ]
2852
- error_code : None ,
2853
- #[ cfg( test) ]
2854
- 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
+ network_update : None ,
2853
+ #[ cfg( test) ]
2854
+ error_code : None ,
2855
+ #[ cfg( test) ]
2856
+ error_data : None ,
2857
+ }
2858
+ ) ;
2859
+ outbounds. remove ( & mpp_id) ;
2860
+ } ,
2861
+ _ => {
2862
+ self . pending_events . lock ( ) . unwrap ( ) . push (
2863
+ events:: Event :: MPPFragmentFailed {
2864
+ payment_hash,
2865
+ payment_path : path. clone ( )
2866
+ }
2867
+ ) ;
2855
2868
}
2856
- ) ;
2857
- if sessions. len ( ) == 0 {
2858
- outbounds. remove ( & mpp_id) ;
2859
2869
}
2860
2870
}
2861
2871
} else {
@@ -2886,12 +2896,14 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2886
2896
let mut session_priv_bytes = [ 0 ; 32 ] ;
2887
2897
session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
2888
2898
let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
2899
+ let mut partial_failure = true ;
2889
2900
if let Some ( sessions) = outbounds. get_mut ( & mpp_id) {
2890
2901
if !sessions. remove ( & session_priv_bytes) {
2891
2902
log_trace ! ( self . logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
2892
2903
return ;
2893
2904
}
2894
2905
if sessions. len ( ) == 0 {
2906
+ partial_failure = false ;
2895
2907
outbounds. remove ( & mpp_id) ;
2896
2908
}
2897
2909
} else {
@@ -2909,42 +2921,60 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2909
2921
// TODO: If we decided to blame ourselves (or one of our channels) in
2910
2922
// process_onion_failure we should close that channel as it implies our
2911
2923
// 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
+ }
2923
2944
} ,
2924
2945
& 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
+ }
2948
2978
}
2949
2979
}
2950
2980
} ,
0 commit comments