Skip to content

Commit acb584d

Browse files
committed
LSPS2ServiceHandler API: Avoid explictly dropping locks
We previously added some explict `drop`s to make sure to drop locks before persisting. While clippy warned us about them, they seemed perfectly functional. However, it weirdly seems that `cargo` will run the same static analysis on dependencies, which has LDK Node builds fail with many dreaded 'isn't `Send`' error whenever we touch the async `LSPS2ServiceHandler` API. Here, we simply believe clippy that this is a bad idea and use scoping over explict `drop`s to ensure we don't hold them anymore when persisting.
1 parent 7926fb9 commit acb584d

File tree

1 file changed

+88
-93
lines changed

1 file changed

+88
-93
lines changed

lightning-liquidity/src/lsps2/service.rs

Lines changed: 88 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -771,16 +771,14 @@ where
771771
/// [`ChannelManager::create_channel`]: lightning::ln::channelmanager::ChannelManager::create_channel
772772
/// [`ChannelManager::get_intercept_scid`]: lightning::ln::channelmanager::ChannelManager::get_intercept_scid
773773
/// [`LSPS2ServiceEvent::BuyRequest`]: crate::lsps2::event::LSPS2ServiceEvent::BuyRequest
774-
#[allow(clippy::await_holding_lock)]
775774
pub async fn invoice_parameters_generated(
776775
&self, counterparty_node_id: &PublicKey, request_id: LSPSRequestId, intercept_scid: u64,
777776
cltv_expiry_delta: u32, client_trusts_lsp: bool, user_channel_id: u128,
778777
) -> Result<(), APIError> {
779778
let mut message_queue_notifier = self.pending_messages.notifier();
780779
let mut should_persist = false;
781780

782-
let outer_state_lock = self.per_peer_state.read().unwrap();
783-
match outer_state_lock.get(counterparty_node_id) {
781+
match self.per_peer_state.read().unwrap().get(counterparty_node_id) {
784782
Some(inner_state_lock) => {
785783
let mut peer_state_lock = inner_state_lock.lock().unwrap();
786784

@@ -827,8 +825,6 @@ where
827825
},
828826
};
829827

830-
drop(outer_state_lock);
831-
832828
if should_persist {
833829
self.persist_peer_state(*counterparty_node_id).await.map_err(|e| {
834830
APIError::APIMisuseError {
@@ -855,16 +851,16 @@ where
855851
///
856852
/// [`Event::HTLCIntercepted`]: lightning::events::Event::HTLCIntercepted
857853
/// [`LSPS2ServiceEvent::OpenChannel`]: crate::lsps2::event::LSPS2ServiceEvent::OpenChannel
858-
#[allow(clippy::await_holding_lock)]
859854
pub async fn htlc_intercepted(
860855
&self, intercept_scid: u64, intercept_id: InterceptId, expected_outbound_amount_msat: u64,
861856
payment_hash: PaymentHash,
862857
) -> Result<(), APIError> {
863858
let event_queue_notifier = self.pending_events.notifier();
864859
let mut should_persist = None;
865860

866-
let peer_by_intercept_scid = self.peer_by_intercept_scid.read().unwrap();
867-
if let Some(counterparty_node_id) = peer_by_intercept_scid.get(&intercept_scid) {
861+
if let Some(counterparty_node_id) =
862+
self.peer_by_intercept_scid.read().unwrap().get(&intercept_scid)
863+
{
868864
let outer_state_lock = self.per_peer_state.read().unwrap();
869865
match outer_state_lock.get(counterparty_node_id) {
870866
Some(inner_state_lock) => {
@@ -939,8 +935,6 @@ where
939935
}
940936
}
941937

942-
drop(peer_by_intercept_scid);
943-
944938
if let Some(counterparty_node_id) = should_persist {
945939
self.persist_peer_state(counterparty_node_id).await.map_err(|e| {
946940
APIError::APIMisuseError {
@@ -1131,55 +1125,57 @@ where
11311125
/// open, as it only affects the local LSPS2 state and doesn't affect any channels that
11321126
/// might already exist on-chain. Any pending channel open attempts must be managed
11331127
/// separately.
1134-
#[allow(clippy::await_holding_lock)]
11351128
pub async fn channel_open_abandoned(
11361129
&self, counterparty_node_id: &PublicKey, user_channel_id: u128,
11371130
) -> Result<(), APIError> {
1138-
let outer_state_lock = self.per_peer_state.read().unwrap();
1139-
let inner_state_lock =
1140-
outer_state_lock.get(counterparty_node_id).ok_or_else(|| APIError::APIMisuseError {
1141-
err: format!("No counterparty state for: {}", counterparty_node_id),
1142-
})?;
1143-
let mut peer_state = inner_state_lock.lock().unwrap();
1144-
1145-
let intercept_scid = peer_state
1146-
.intercept_scid_by_user_channel_id
1147-
.get(&user_channel_id)
1148-
.copied()
1149-
.ok_or_else(|| APIError::APIMisuseError {
1150-
err: format!("Could not find a channel with user_channel_id {}", user_channel_id),
1131+
{
1132+
let outer_state_lock = self.per_peer_state.read().unwrap();
1133+
let inner_state_lock = outer_state_lock.get(counterparty_node_id).ok_or_else(|| {
1134+
APIError::APIMisuseError {
1135+
err: format!("No counterparty state for: {}", counterparty_node_id),
1136+
}
11511137
})?;
1138+
let mut peer_state = inner_state_lock.lock().unwrap();
11521139

1153-
let jit_channel = peer_state
1154-
.outbound_channels_by_intercept_scid
1155-
.get(&intercept_scid)
1156-
.ok_or_else(|| APIError::APIMisuseError {
1140+
let intercept_scid = peer_state
1141+
.intercept_scid_by_user_channel_id
1142+
.get(&user_channel_id)
1143+
.copied()
1144+
.ok_or_else(|| APIError::APIMisuseError {
1145+
err: format!(
1146+
"Could not find a channel with user_channel_id {}",
1147+
user_channel_id
1148+
),
1149+
})?;
1150+
1151+
let jit_channel = peer_state
1152+
.outbound_channels_by_intercept_scid
1153+
.get(&intercept_scid)
1154+
.ok_or_else(|| APIError::APIMisuseError {
11571155
err: format!(
11581156
"Failed to map intercept_scid {} for user_channel_id {} to a channel.",
11591157
intercept_scid, user_channel_id,
11601158
),
11611159
})?;
11621160

1163-
let is_pending = matches!(
1164-
jit_channel.state,
1165-
OutboundJITChannelState::PendingInitialPayment { .. }
1166-
| OutboundJITChannelState::PendingChannelOpen { .. }
1167-
);
1168-
1169-
if !is_pending {
1170-
return Err(APIError::APIMisuseError {
1171-
err: "Cannot abandon channel open after channel creation or payment forwarding"
1172-
.to_string(),
1173-
});
1174-
}
1161+
let is_pending = matches!(
1162+
jit_channel.state,
1163+
OutboundJITChannelState::PendingInitialPayment { .. }
1164+
| OutboundJITChannelState::PendingChannelOpen { .. }
1165+
);
11751166

1176-
peer_state.intercept_scid_by_user_channel_id.remove(&user_channel_id);
1177-
peer_state.outbound_channels_by_intercept_scid.remove(&intercept_scid);
1178-
peer_state.intercept_scid_by_channel_id.retain(|_, &mut scid| scid != intercept_scid);
1179-
peer_state.needs_persist |= true;
1167+
if !is_pending {
1168+
return Err(APIError::APIMisuseError {
1169+
err: "Cannot abandon channel open after channel creation or payment forwarding"
1170+
.to_string(),
1171+
});
1172+
}
11801173

1181-
drop(peer_state);
1182-
drop(outer_state_lock);
1174+
peer_state.intercept_scid_by_user_channel_id.remove(&user_channel_id);
1175+
peer_state.outbound_channels_by_intercept_scid.remove(&intercept_scid);
1176+
peer_state.intercept_scid_by_channel_id.retain(|_, &mut scid| scid != intercept_scid);
1177+
peer_state.needs_persist |= true;
1178+
}
11831179

11841180
self.persist_peer_state(*counterparty_node_id).await.map_err(|e| {
11851181
APIError::APIMisuseError {
@@ -1197,62 +1193,63 @@ where
11971193
/// state so that the payer may try the payment again.
11981194
///
11991195
/// [`LSPS2ServiceEvent::OpenChannel`]: crate::lsps2::event::LSPS2ServiceEvent::OpenChannel
1200-
#[allow(clippy::await_holding_lock)]
12011196
pub async fn channel_open_failed(
12021197
&self, counterparty_node_id: &PublicKey, user_channel_id: u128,
12031198
) -> Result<(), APIError> {
1204-
let outer_state_lock = self.per_peer_state.read().unwrap();
1199+
{
1200+
let outer_state_lock = self.per_peer_state.read().unwrap();
12051201

1206-
let inner_state_lock =
1207-
outer_state_lock.get(counterparty_node_id).ok_or_else(|| APIError::APIMisuseError {
1208-
err: format!("No counterparty state for: {}", counterparty_node_id),
1202+
let inner_state_lock = outer_state_lock.get(counterparty_node_id).ok_or_else(|| {
1203+
APIError::APIMisuseError {
1204+
err: format!("No counterparty state for: {}", counterparty_node_id),
1205+
}
12091206
})?;
12101207

1211-
let mut peer_state = inner_state_lock.lock().unwrap();
1208+
let mut peer_state = inner_state_lock.lock().unwrap();
12121209

1213-
let intercept_scid = peer_state
1214-
.intercept_scid_by_user_channel_id
1215-
.get(&user_channel_id)
1216-
.copied()
1217-
.ok_or_else(|| APIError::APIMisuseError {
1218-
err: format!("Could not find a channel with user_channel_id {}", user_channel_id),
1219-
})?;
1210+
let intercept_scid = peer_state
1211+
.intercept_scid_by_user_channel_id
1212+
.get(&user_channel_id)
1213+
.copied()
1214+
.ok_or_else(|| APIError::APIMisuseError {
1215+
err: format!(
1216+
"Could not find a channel with user_channel_id {}",
1217+
user_channel_id
1218+
),
1219+
})?;
12201220

1221-
let jit_channel = peer_state
1222-
.outbound_channels_by_intercept_scid
1223-
.get_mut(&intercept_scid)
1224-
.ok_or_else(|| APIError::APIMisuseError {
1225-
err: format!(
1226-
"Failed to map intercept_scid {} for user_channel_id {} to a channel.",
1227-
intercept_scid, user_channel_id,
1228-
),
1229-
})?;
1221+
let jit_channel = peer_state
1222+
.outbound_channels_by_intercept_scid
1223+
.get_mut(&intercept_scid)
1224+
.ok_or_else(|| APIError::APIMisuseError {
1225+
err: format!(
1226+
"Failed to map intercept_scid {} for user_channel_id {} to a channel.",
1227+
intercept_scid, user_channel_id,
1228+
),
1229+
})?;
1230+
1231+
if let OutboundJITChannelState::PendingChannelOpen { payment_queue, .. } =
1232+
&mut jit_channel.state
1233+
{
1234+
let intercepted_htlcs = payment_queue.clear();
1235+
for htlc in intercepted_htlcs {
1236+
self.channel_manager.get_cm().fail_htlc_backwards_with_reason(
1237+
&htlc.payment_hash,
1238+
FailureCode::TemporaryNodeFailure,
1239+
);
1240+
}
12301241

1231-
if let OutboundJITChannelState::PendingChannelOpen { payment_queue, .. } =
1232-
&mut jit_channel.state
1233-
{
1234-
let intercepted_htlcs = payment_queue.clear();
1235-
for htlc in intercepted_htlcs {
1236-
self.channel_manager.get_cm().fail_htlc_backwards_with_reason(
1237-
&htlc.payment_hash,
1238-
FailureCode::TemporaryNodeFailure,
1239-
);
1242+
jit_channel.state = OutboundJITChannelState::PendingInitialPayment {
1243+
payment_queue: PaymentQueue::new(),
1244+
};
1245+
} else {
1246+
return Err(APIError::APIMisuseError {
1247+
err: "Channel is not in the PendingChannelOpen state.".to_string(),
1248+
});
12401249
}
12411250

1242-
jit_channel.state = OutboundJITChannelState::PendingInitialPayment {
1243-
payment_queue: PaymentQueue::new(),
1244-
};
1245-
} else {
1246-
return Err(APIError::APIMisuseError {
1247-
err: "Channel is not in the PendingChannelOpen state.".to_string(),
1248-
});
1251+
peer_state.needs_persist |= true;
12491252
}
1250-
1251-
peer_state.needs_persist |= true;
1252-
1253-
drop(peer_state);
1254-
drop(outer_state_lock);
1255-
12561253
self.persist_peer_state(*counterparty_node_id).await.map_err(|e| {
12571254
APIError::APIMisuseError {
12581255
err: format!("Failed to persist peer state for {}: {}", counterparty_node_id, e),
@@ -1268,7 +1265,6 @@ where
12681265
/// we need to forward a payment over otherwise it will be ignored.
12691266
///
12701267
/// [`Event::ChannelReady`]: lightning::events::Event::ChannelReady
1271-
#[allow(clippy::await_holding_lock)]
12721268
pub async fn channel_ready(
12731269
&self, user_channel_id: u128, channel_id: &ChannelId, counterparty_node_id: &PublicKey,
12741270
) -> Result<(), APIError> {
@@ -1277,8 +1273,7 @@ where
12771273
let mut peer_by_channel_id = self.peer_by_channel_id.write().unwrap();
12781274
peer_by_channel_id.insert(*channel_id, *counterparty_node_id);
12791275
}
1280-
let outer_state_lock = self.per_peer_state.read().unwrap();
1281-
match outer_state_lock.get(counterparty_node_id) {
1276+
match self.per_peer_state.read().unwrap().get(counterparty_node_id) {
12821277
Some(inner_state_lock) => {
12831278
let mut peer_state = inner_state_lock.lock().unwrap();
12841279
if let Some(intercept_scid) =

0 commit comments

Comments
 (0)