@@ -32,7 +32,7 @@ use crate::prelude::{new_hash_map, HashMap};
32
32
use crate :: sync:: { Arc , Mutex , MutexGuard , RwLock } ;
33
33
34
34
use lightning:: events:: HTLCHandlingFailureType ;
35
- use lightning:: ln:: channelmanager:: { AChannelManager , InterceptId } ;
35
+ use lightning:: ln:: channelmanager:: { AChannelManager , FailureCode , InterceptId } ;
36
36
use lightning:: ln:: msgs:: { ErrorAction , LightningError } ;
37
37
use lightning:: ln:: types:: ChannelId ;
38
38
use lightning:: util:: errors:: APIError ;
@@ -985,6 +985,128 @@ where
985
985
Ok ( ( ) )
986
986
}
987
987
988
+ /// Abandons a pending JIT‐open flow for `user_channel_id`, removing all local state.
989
+ ///
990
+ /// This removes the intercept SCID, any outbound channel state, and associated
991
+ /// channel‐ID mappings for the specified `user_channel_id`, but only while no payment
992
+ /// has been forwarded yet and no channel has been opened on-chain.
993
+ ///
994
+ /// Returns an error if:
995
+ /// - there is no channel matching `user_channel_id`, or
996
+ /// - a payment has already been forwarded or a channel has already been opened
997
+ ///
998
+ /// Note: this does *not* close or roll back any on‐chain channel which may already
999
+ /// have been opened. The caller must call this before or instead of initiating the channel
1000
+ /// open, as it only affects the local LSPS2 state and doesn't affect any channels that
1001
+ /// might already exist on-chain. Any pending channel open attempts must be managed
1002
+ /// separately.
1003
+ pub fn channel_open_abandoned (
1004
+ & self , counterparty_node_id : & PublicKey , user_channel_id : u128 ,
1005
+ ) -> Result < ( ) , APIError > {
1006
+ let outer_state_lock = self . per_peer_state . read ( ) . unwrap ( ) ;
1007
+ let inner_state_lock =
1008
+ outer_state_lock. get ( counterparty_node_id) . ok_or_else ( || APIError :: APIMisuseError {
1009
+ err : format ! ( "No counterparty state for: {}" , counterparty_node_id) ,
1010
+ } ) ?;
1011
+ let mut peer_state = inner_state_lock. lock ( ) . unwrap ( ) ;
1012
+
1013
+ let intercept_scid = peer_state
1014
+ . intercept_scid_by_user_channel_id
1015
+ . get ( & user_channel_id)
1016
+ . copied ( )
1017
+ . ok_or_else ( || APIError :: APIMisuseError {
1018
+ err : format ! ( "Could not find a channel with user_channel_id {}" , user_channel_id) ,
1019
+ } ) ?;
1020
+
1021
+ let jit_channel = peer_state
1022
+ . outbound_channels_by_intercept_scid
1023
+ . get ( & intercept_scid)
1024
+ . ok_or_else ( || APIError :: APIMisuseError {
1025
+ err : format ! (
1026
+ "Failed to map intercept_scid {} for user_channel_id {} to a channel." ,
1027
+ intercept_scid, user_channel_id,
1028
+ ) ,
1029
+ } ) ?;
1030
+
1031
+ let is_pending = matches ! (
1032
+ jit_channel. state,
1033
+ OutboundJITChannelState :: PendingInitialPayment { .. }
1034
+ | OutboundJITChannelState :: PendingChannelOpen { .. }
1035
+ ) ;
1036
+
1037
+ if !is_pending {
1038
+ return Err ( APIError :: APIMisuseError {
1039
+ err : "Cannot abandon channel open after channel creation or payment forwarding"
1040
+ . to_string ( ) ,
1041
+ } ) ;
1042
+ }
1043
+
1044
+ peer_state. intercept_scid_by_user_channel_id . remove ( & user_channel_id) ;
1045
+ peer_state. outbound_channels_by_intercept_scid . remove ( & intercept_scid) ;
1046
+ peer_state. intercept_scid_by_channel_id . retain ( |_, & mut scid| scid != intercept_scid) ;
1047
+
1048
+ Ok ( ( ) )
1049
+ }
1050
+
1051
+ /// Used to fail intercepted HTLCs backwards when a channel open attempt ultimately fails.
1052
+ ///
1053
+ /// This function should be called after receiving an [`LSPS2ServiceEvent::OpenChannel`] event
1054
+ /// but only if the channel could not be successfully established. It resets the JIT channel
1055
+ /// state so that the payer may try the payment again.
1056
+ ///
1057
+ /// [`LSPS2ServiceEvent::OpenChannel`]: crate::lsps2::event::LSPS2ServiceEvent::OpenChannel
1058
+ pub fn channel_open_failed (
1059
+ & self , counterparty_node_id : & PublicKey , user_channel_id : u128 ,
1060
+ ) -> Result < ( ) , APIError > {
1061
+ let outer_state_lock = self . per_peer_state . read ( ) . unwrap ( ) ;
1062
+
1063
+ let inner_state_lock =
1064
+ outer_state_lock. get ( counterparty_node_id) . ok_or_else ( || APIError :: APIMisuseError {
1065
+ err : format ! ( "No counterparty state for: {}" , counterparty_node_id) ,
1066
+ } ) ?;
1067
+
1068
+ let mut peer_state = inner_state_lock. lock ( ) . unwrap ( ) ;
1069
+
1070
+ let intercept_scid = peer_state
1071
+ . intercept_scid_by_user_channel_id
1072
+ . get ( & user_channel_id)
1073
+ . copied ( )
1074
+ . ok_or_else ( || APIError :: APIMisuseError {
1075
+ err : format ! ( "Could not find a channel with user_channel_id {}" , user_channel_id) ,
1076
+ } ) ?;
1077
+
1078
+ let jit_channel = peer_state
1079
+ . outbound_channels_by_intercept_scid
1080
+ . get_mut ( & intercept_scid)
1081
+ . ok_or_else ( || APIError :: APIMisuseError {
1082
+ err : format ! (
1083
+ "Failed to map intercept_scid {} for user_channel_id {} to a channel." ,
1084
+ intercept_scid, user_channel_id,
1085
+ ) ,
1086
+ } ) ?;
1087
+
1088
+ if let OutboundJITChannelState :: PendingChannelOpen { payment_queue, .. } =
1089
+ & mut jit_channel. state
1090
+ {
1091
+ let intercepted_htlcs = payment_queue. clear ( ) ;
1092
+ for htlc in intercepted_htlcs {
1093
+ self . channel_manager . get_cm ( ) . fail_htlc_backwards_with_reason (
1094
+ & htlc. payment_hash ,
1095
+ FailureCode :: TemporaryNodeFailure ,
1096
+ ) ;
1097
+ }
1098
+
1099
+ jit_channel. state = OutboundJITChannelState :: PendingInitialPayment {
1100
+ payment_queue : PaymentQueue :: new ( ) ,
1101
+ } ;
1102
+ Ok ( ( ) )
1103
+ } else {
1104
+ Err ( APIError :: APIMisuseError {
1105
+ err : "Channel is not in the PendingChannelOpen state." . to_string ( ) ,
1106
+ } )
1107
+ }
1108
+ }
1109
+
988
1110
/// Forward [`Event::ChannelReady`] event parameters into this function.
989
1111
///
990
1112
/// Will forward the intercepted HTLC if it matches a channel
0 commit comments