@@ -19,7 +19,7 @@ use crate::prelude::{HashMap, String, ToString, Vec};
19
19
use crate :: sync:: { Arc , Mutex , RwLock } ;
20
20
21
21
use lightning:: events:: HTLCDestination ;
22
- use lightning:: ln:: channelmanager:: { AChannelManager , InterceptId } ;
22
+ use lightning:: ln:: channelmanager:: { AChannelManager , FailureCode , InterceptId } ;
23
23
use lightning:: ln:: msgs:: { ErrorAction , LightningError } ;
24
24
use lightning:: ln:: { ChannelId , PaymentHash } ;
25
25
use lightning:: util:: errors:: APIError ;
@@ -362,7 +362,13 @@ impl OutboundJITChannelState {
362
362
let mut payment_queue_lock = payment_queue. lock ( ) . unwrap ( ) ;
363
363
let payment_forwarded =
364
364
OutboundJITChannelState :: PaymentForwarded { channel_id : * channel_id } ;
365
- let forward_htlcs = ForwardHTLCsAction ( * channel_id, payment_queue_lock. clear ( ) ) ;
365
+ let htlcs = payment_queue_lock
366
+ . clear ( )
367
+ . into_iter ( )
368
+ . map ( |( _, htlcs) | htlcs)
369
+ . flatten ( )
370
+ . collect ( ) ;
371
+ let forward_htlcs = ForwardHTLCsAction ( * channel_id, htlcs) ;
366
372
Ok ( ( payment_forwarded, Some ( forward_htlcs) ) )
367
373
} ,
368
374
OutboundJITChannelState :: PaymentForwarded { channel_id } => {
@@ -898,6 +904,79 @@ where
898
904
Ok ( ( ) )
899
905
}
900
906
907
+ /// Used by LSP to fail intercepted htlcs backwards when the channel open fails for any reason.
908
+ ///
909
+ /// Should be called in response to receiving a [`LSPS2ServiceEvent::OpenChannel`] event.
910
+ ///
911
+ /// The JIT channel state is reset such that the payer can attempt payment again.
912
+ /// [`LSPS2ServiceEvent::OpenChannel`]: crate::lsps2::event::LSPS2ServiceEvent::OpenChannel
913
+ pub fn channel_open_failed (
914
+ & self , counterparty_node_id : & PublicKey , user_channel_id : u128 ,
915
+ ) -> Result < ( ) , APIError > {
916
+ let outer_state_lock = self . per_peer_state . read ( ) . unwrap ( ) ;
917
+ match outer_state_lock. get ( counterparty_node_id) {
918
+ Some ( inner_state_lock) => {
919
+ let mut peer_state = inner_state_lock. lock ( ) . unwrap ( ) ;
920
+
921
+ if let Some ( intercept_scid) =
922
+ peer_state. intercept_scid_by_user_channel_id . get ( & user_channel_id) . copied ( )
923
+ {
924
+ if let Some ( jit_channel) =
925
+ peer_state. outbound_channels_by_intercept_scid . get_mut ( & intercept_scid)
926
+ {
927
+ let new_state = if let OutboundJITChannelState :: PendingChannelOpen {
928
+ payment_queue,
929
+ ..
930
+ } = & jit_channel. state
931
+ {
932
+ let mut queue = payment_queue. lock ( ) . unwrap ( ) ;
933
+ let payment_hashes = queue
934
+ . clear ( )
935
+ . into_iter ( )
936
+ . map ( |( payment_hash, _) | payment_hash)
937
+ . collect :: < Vec < _ > > ( ) ;
938
+ for payment_hash in payment_hashes {
939
+ self . channel_manager . get_cm ( ) . fail_htlc_backwards_with_reason (
940
+ & payment_hash,
941
+ FailureCode :: TemporaryNodeFailure ,
942
+ ) ;
943
+ }
944
+ OutboundJITChannelState :: PendingInitialPayment {
945
+ payment_queue : payment_queue. clone ( ) ,
946
+ }
947
+ } else {
948
+ return Err ( APIError :: APIMisuseError {
949
+ err : format ! ( "Channel is not in the PendingChannelOpen state." , ) ,
950
+ } ) ;
951
+ } ;
952
+ jit_channel. state = new_state;
953
+ } else {
954
+ return Err ( APIError :: APIMisuseError {
955
+ err : format ! (
956
+ "Failed to map the stored intercept_scid {} for the provided user_channel_id {} to a channel." ,
957
+ intercept_scid,
958
+ user_channel_id,
959
+ ) ,
960
+ } ) ;
961
+ }
962
+ } else {
963
+ return Err ( APIError :: APIMisuseError {
964
+ err : format ! (
965
+ "Could not find a channel with user_channel_id {}" ,
966
+ user_channel_id
967
+ ) ,
968
+ } ) ;
969
+ }
970
+ } ,
971
+ None => {
972
+ return Err ( APIError :: APIMisuseError {
973
+ err : format ! ( "No counterparty state for: {}" , counterparty_node_id) ,
974
+ } ) ;
975
+ } ,
976
+ }
977
+ Ok ( ( ) )
978
+ }
979
+
901
980
/// Forward [`Event::ChannelReady`] event parameters into this function.
902
981
///
903
982
/// Will forward the intercepted HTLC if it matches a channel
0 commit comments