@@ -32,7 +32,7 @@ use crate::prelude::{new_hash_map, HashMap};
3232use crate :: sync:: { Arc , Mutex , MutexGuard , RwLock } ;
3333
3434use lightning:: events:: HTLCHandlingFailureType ;
35- use lightning:: ln:: channelmanager:: { AChannelManager , InterceptId } ;
35+ use lightning:: ln:: channelmanager:: { AChannelManager , FailureCode , InterceptId } ;
3636use lightning:: ln:: msgs:: { ErrorAction , LightningError } ;
3737use lightning:: ln:: types:: ChannelId ;
3838use lightning:: util:: errors:: APIError ;
@@ -985,6 +985,128 @@ where
985985 Ok ( ( ) )
986986 }
987987
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+
9881110 /// Forward [`Event::ChannelReady`] event parameters into this function.
9891111 ///
9901112 /// Will forward the intercepted HTLC if it matches a channel
0 commit comments