11
11
12
12
use alloc:: string:: { String , ToString } ;
13
13
use alloc:: vec:: Vec ;
14
+ use lightning:: util:: hash_tables:: HashSet ;
14
15
15
16
use core:: ops:: Deref ;
16
17
use core:: sync:: atomic:: { AtomicUsize , Ordering } ;
@@ -32,7 +33,7 @@ use crate::prelude::{new_hash_map, HashMap};
32
33
use crate :: sync:: { Arc , Mutex , MutexGuard , RwLock } ;
33
34
34
35
use lightning:: events:: HTLCDestination ;
35
- use lightning:: ln:: channelmanager:: { AChannelManager , InterceptId } ;
36
+ use lightning:: ln:: channelmanager:: { AChannelManager , FailureCode , InterceptId } ;
36
37
use lightning:: ln:: msgs:: { ErrorAction , LightningError } ;
37
38
use lightning:: ln:: types:: ChannelId ;
38
39
use lightning:: util:: errors:: APIError ;
@@ -1005,6 +1006,104 @@ where
1005
1006
Ok ( ( ) )
1006
1007
}
1007
1008
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
+
1008
1107
/// Forward [`Event::ChannelReady`] event parameters into this function.
1009
1108
///
1010
1109
/// Will forward the intercepted HTLC if it matches a channel
0 commit comments