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