@@ -32,7 +32,7 @@ use crate::prelude::{new_hash_map, HashMap};
3232use crate :: sync:: { Arc , Mutex , MutexGuard , RwLock } ;
3333
3434use lightning:: events:: HTLCDestination ;
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 ;
@@ -1005,6 +1005,104 @@ where
10051005 Ok ( ( ) )
10061006 }
10071007
1008+ /// Abandons a channel open attempt by pruning all state related to the channel open.
1009+ ///
1010+ /// This function should be used when a channel open attempt is to be abandoned entirely,
1011+ /// without resetting the state for a potential payment retry. It removes the intercept SCID
1012+ /// mapping along with any outbound channel state and related channel ID mappings associated with
1013+ /// the specified `user_channel_id`.
1014+ pub fn channel_open_abandoned (
1015+ & self , counterparty_node_id : & PublicKey , user_channel_id : u128 ,
1016+ ) -> Result < ( ) , APIError > {
1017+ let outer_state_lock = self . per_peer_state . read ( ) . unwrap ( ) ;
1018+ let inner_state_lock =
1019+ outer_state_lock. get ( counterparty_node_id) . ok_or_else ( || APIError :: APIMisuseError {
1020+ err : format ! ( "No counterparty state for: {}" , counterparty_node_id) ,
1021+ } ) ?;
1022+ let mut peer_state = inner_state_lock. lock ( ) . unwrap ( ) ;
1023+
1024+ let intercept_scid = peer_state
1025+ . intercept_scid_by_user_channel_id
1026+ . remove ( & user_channel_id)
1027+ . ok_or_else ( || APIError :: APIMisuseError {
1028+ err : format ! ( "Could not find a channel with user_channel_id {}" , user_channel_id) ,
1029+ } ) ?;
1030+
1031+ peer_state. outbound_channels_by_intercept_scid . remove ( & intercept_scid) ;
1032+
1033+ peer_state. intercept_scid_by_channel_id . retain ( |_, & mut scid| scid != intercept_scid) ;
1034+
1035+ Ok ( ( ) )
1036+ }
1037+
1038+ /// Used to fail intercepted HTLCs backwards when a channel open attempt ultimately fails.
1039+ ///
1040+ /// This function should be called after receiving an [`LSPS2ServiceEvent::OpenChannel`] event
1041+ /// but only if the channel could not be successfully established. It resets the JIT channel
1042+ /// state so that the payer may try the payment again.
1043+ ///
1044+ /// [`LSPS2ServiceEvent::OpenChannel`]: crate::lsps2::event::LSPS2ServiceEvent::OpenChannel
1045+ pub fn channel_open_failed (
1046+ & self , counterparty_node_id : & PublicKey , user_channel_id : u128 ,
1047+ ) -> Result < ( ) , APIError > {
1048+ let outer_state_lock = self . per_peer_state . read ( ) . unwrap ( ) ;
1049+
1050+ let inner_state_lock =
1051+ outer_state_lock. get ( counterparty_node_id) . ok_or_else ( || APIError :: APIMisuseError {
1052+ err : format ! ( "No counterparty state for: {}" , counterparty_node_id) ,
1053+ } ) ?;
1054+
1055+ let mut peer_state = inner_state_lock. lock ( ) . unwrap ( ) ;
1056+
1057+ let intercept_scid = peer_state
1058+ . intercept_scid_by_user_channel_id
1059+ . get ( & user_channel_id)
1060+ . copied ( )
1061+ . ok_or_else ( || APIError :: APIMisuseError {
1062+ err : format ! ( "Could not find a channel with user_channel_id {}" , user_channel_id) ,
1063+ } ) ?;
1064+
1065+ let jit_channel = peer_state
1066+ . outbound_channels_by_intercept_scid
1067+ . get_mut ( & intercept_scid)
1068+ . ok_or_else ( || APIError :: APIMisuseError {
1069+ err : format ! (
1070+ "Failed to map the stored intercept_scid {} for the provided user_channel_id {} to a channel." ,
1071+ intercept_scid, user_channel_id,
1072+ ) ,
1073+ } ) ?;
1074+
1075+ jit_channel. state = match & jit_channel. state {
1076+ OutboundJITChannelState :: PendingChannelOpen { payment_queue, .. } => {
1077+ let mut queue = payment_queue. lock ( ) . unwrap ( ) ;
1078+ let payment_hashes: Vec < _ > = queue
1079+ . clear ( )
1080+ . into_iter ( )
1081+ . map ( |htlc| htlc. payment_hash )
1082+ . collect :: < std:: collections:: HashSet < _ > > ( )
1083+ . into_iter ( )
1084+ . collect ( ) ;
1085+
1086+ for payment_hash in payment_hashes {
1087+ self . channel_manager . get_cm ( ) . fail_htlc_backwards_with_reason (
1088+ & payment_hash,
1089+ FailureCode :: TemporaryNodeFailure ,
1090+ ) ;
1091+ }
1092+ OutboundJITChannelState :: PendingInitialPayment {
1093+ payment_queue : payment_queue. clone ( ) ,
1094+ }
1095+ } ,
1096+ _ => {
1097+ return Err ( APIError :: APIMisuseError {
1098+ err : "Channel is not in the PendingChannelOpen state." . to_string ( ) ,
1099+ } )
1100+ } ,
1101+ } ;
1102+
1103+ Ok ( ( ) )
1104+ }
1105+
10081106 /// Forward [`Event::ChannelReady`] event parameters into this function.
10091107 ///
10101108 /// Will forward the intercepted HTLC if it matches a channel
0 commit comments