Skip to content

Commit de5fdcc

Browse files
fixup: Clean up LSPS2 service code
- Update docs to focus on behavior not internal states - Fix channel_open_abandoned to check before removing SCID - Use mem::take instead of clone in channel_open_failed - Remove unnecessary HashSet when failing HTLCs - Improve error messages
1 parent b0c35ae commit de5fdcc

File tree

1 file changed

+44
-47
lines changed

1 file changed

+44
-47
lines changed

lightning-liquidity/src/lsps2/service.rs

+44-47
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ use lightning::ln::channelmanager::{AChannelManager, FailureCode, InterceptId};
3636
use lightning::ln::msgs::{ErrorAction, LightningError};
3737
use lightning::ln::types::ChannelId;
3838
use lightning::util::errors::APIError;
39-
use lightning::util::hash_tables::HashSet;
4039
use lightning::util::logger::Level;
4140

4241
use lightning_types::payment::PaymentHash;
@@ -989,18 +988,18 @@ where
989988
/// Abandons a pending JIT‐open flow for `user_channel_id`, removing all local state.
990989
///
991990
/// This removes the intercept SCID, any outbound channel state, and associated
992-
/// channel‐ID mappings for the specified `user_channel_id`, but only while the JIT
993-
/// channel is still in `PendingInitialPayment` or `PendingChannelOpen`.
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.
994993
///
995994
/// Returns an error if:
996995
/// - there is no channel matching `user_channel_id`, or
997-
/// - the channel has already advanced past `PendingChannelOpen` (e.g. to
998-
/// `PendingPaymentForward` or beyond).
996+
/// - a payment has already been forwarded or a channel has already been opened
999997
///
1000998
/// Note: this does *not* close or roll back any on‐chain channel which may already
1001-
/// have been opened. The caller must only invoke this before a channel is actually
1002-
/// confirmed (or else provide its own on‐chain cleanup) and is responsible for
1003-
/// managing any pending channel open attempts separately.
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.
10041003
pub fn channel_open_abandoned(
10051004
&self, counterparty_node_id: &PublicKey, user_channel_id: u128,
10061005
) -> Result<(), APIError> {
@@ -1013,28 +1012,37 @@ where
10131012

10141013
let intercept_scid = peer_state
10151014
.intercept_scid_by_user_channel_id
1016-
.remove(&user_channel_id)
1015+
.get(&user_channel_id)
1016+
.copied()
10171017
.ok_or_else(|| APIError::APIMisuseError {
10181018
err: format!("Could not find a channel with user_channel_id {}", user_channel_id),
10191019
})?;
10201020

1021-
if let Some(jit_channel) =
1022-
peer_state.outbound_channels_by_intercept_scid.get(&intercept_scid)
1023-
{
1024-
if !matches!(
1025-
jit_channel.state,
1026-
OutboundJITChannelState::PendingInitialPayment { .. }
1027-
| OutboundJITChannelState::PendingChannelOpen { .. }
1028-
) {
1029-
return Err(APIError::APIMisuseError {
1030-
err: "Cannot abandon channel open after channel creation or payment forwarding"
1031-
.to_string(),
1032-
});
1033-
}
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+
});
10341042
}
10351043

1044+
peer_state.intercept_scid_by_user_channel_id.remove(&user_channel_id);
10361045
peer_state.outbound_channels_by_intercept_scid.remove(&intercept_scid);
1037-
10381046
peer_state.intercept_scid_by_channel_id.retain(|_, &mut scid| scid != intercept_scid);
10391047

10401048
Ok(())
@@ -1077,33 +1085,22 @@ where
10771085
),
10781086
})?;
10791087

1080-
if !matches!(jit_channel.state, OutboundJITChannelState::PendingChannelOpen { .. }) {
1081-
return Err(APIError::APIMisuseError {
1082-
err: "Channel is not in the PendingChannelOpen state.".to_string(),
1083-
});
1084-
}
1085-
1086-
let mut payment_queue = match &jit_channel.state {
1087-
OutboundJITChannelState::PendingChannelOpen { payment_queue, .. } => {
1088-
payment_queue.clone()
1089-
},
1090-
_ => {
1088+
let mut payment_queue =
1089+
if let OutboundJITChannelState::PendingChannelOpen { payment_queue, .. } =
1090+
&mut jit_channel.state
1091+
{
1092+
core::mem::take(payment_queue)
1093+
} else {
10911094
return Err(APIError::APIMisuseError {
10921095
err: "Channel is not in the PendingChannelOpen state.".to_string(),
10931096
});
1094-
},
1095-
};
1096-
let payment_hashes: Vec<_> = payment_queue
1097-
.clear()
1098-
.into_iter()
1099-
.map(|htlc| htlc.payment_hash)
1100-
.collect::<HashSet<_>>()
1101-
.into_iter()
1102-
.collect();
1103-
for payment_hash in payment_hashes {
1104-
self.channel_manager
1105-
.get_cm()
1106-
.fail_htlc_backwards_with_reason(&payment_hash, FailureCode::TemporaryNodeFailure);
1097+
};
1098+
1099+
for htlc in payment_queue.clear() {
1100+
self.channel_manager.get_cm().fail_htlc_backwards_with_reason(
1101+
&htlc.payment_hash,
1102+
FailureCode::TemporaryNodeFailure,
1103+
);
11071104
}
11081105

11091106
jit_channel.state = OutboundJITChannelState::PendingInitialPayment { payment_queue };

0 commit comments

Comments
 (0)