Skip to content

Commit 2233201

Browse files
committed
Add force_close method to allow channel force-closure
.. which we somehow so far ommitted exposing in the API. We now introduce a `force_close` method and broadcast if the counterparty is not trusted.
1 parent fcec338 commit 2233201

File tree

2 files changed

+70
-14
lines changed

2 files changed

+70
-14
lines changed

bindings/ldk_node.udl

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ interface Node {
7272
[Throws=NodeError]
7373
void close_channel([ByRef]UserChannelId user_channel_id, PublicKey counterparty_node_id);
7474
[Throws=NodeError]
75+
void force_close_channel([ByRef]UserChannelId user_channel_id, PublicKey counterparty_node_id);
76+
[Throws=NodeError]
7577
void update_channel_config([ByRef]UserChannelId user_channel_id, PublicKey counterparty_node_id, ChannelConfig channel_config);
7678
[Throws=NodeError]
7779
void sync_wallets();

src/lib.rs

+68-14
Original file line numberDiff line numberDiff line change
@@ -1176,30 +1176,84 @@ impl Node {
11761176
}
11771177

11781178
/// Close a previously opened channel.
1179+
///
1180+
/// Will attempt to close a channel coopertively. If this fails, users might need to resort to
1181+
/// [`Node::force_close_channel`].
11791182
pub fn close_channel(
11801183
&self, user_channel_id: &UserChannelId, counterparty_node_id: PublicKey,
1184+
) -> Result<(), Error> {
1185+
self.close_channel_internal(user_channel_id, counterparty_node_id, false)
1186+
}
1187+
1188+
/// Force-close a previously opened channel.
1189+
///
1190+
/// Will force-close the channel, potentially broadcasting our latest state. Note that in
1191+
/// contrast to cooperative closure, force-closing will have the channel funds time-locked,
1192+
/// i.e., they will only be available after the counterparty had time to contest our claim.
1193+
/// Force-closing channels also more costly in terms of on-chain fees. So cooperative closure
1194+
/// should always be preferred (and tried first).
1195+
///
1196+
/// Broadcasting the closing transactions will be omitted for Anchor channels if we trust the
1197+
/// counterparty to broadcast for us (see [`AnchorChannelsConfig::trusted_peers_no_reserve`]
1198+
/// for more information).
1199+
pub fn force_close_channel(
1200+
&self, user_channel_id: &UserChannelId, counterparty_node_id: PublicKey,
1201+
) -> Result<(), Error> {
1202+
self.close_channel_internal(user_channel_id, counterparty_node_id, true)
1203+
}
1204+
1205+
fn close_channel_internal(
1206+
&self, user_channel_id: &UserChannelId, counterparty_node_id: PublicKey, force: bool,
11811207
) -> Result<(), Error> {
11821208
let open_channels =
11831209
self.channel_manager.list_channels_with_counterparty(&counterparty_node_id);
11841210
if let Some(channel_details) =
11851211
open_channels.iter().find(|c| c.user_channel_id == user_channel_id.0)
11861212
{
1187-
match self
1188-
.channel_manager
1189-
.close_channel(&channel_details.channel_id, &counterparty_node_id)
1190-
{
1191-
Ok(_) => {
1192-
// Check if this was the last open channel, if so, forget the peer.
1193-
if open_channels.len() == 1 {
1194-
self.peer_store.remove_peer(&counterparty_node_id)?;
1195-
}
1196-
Ok(())
1197-
},
1198-
Err(_) => Err(Error::ChannelClosingFailed),
1213+
if force {
1214+
if self.config.anchor_channels_config.as_ref().map_or(false, |acc| {
1215+
acc.trusted_peers_no_reserve.contains(&counterparty_node_id)
1216+
}) {
1217+
self.channel_manager
1218+
.force_close_without_broadcasting_txn(
1219+
&channel_details.channel_id,
1220+
&counterparty_node_id,
1221+
)
1222+
.map_err(|e| {
1223+
log_error!(
1224+
self.logger,
1225+
"Failed to force-close channel to trusted peer: {:?}",
1226+
e
1227+
);
1228+
Error::ChannelClosingFailed
1229+
})?;
1230+
} else {
1231+
self.channel_manager
1232+
.force_close_broadcasting_latest_txn(
1233+
&channel_details.channel_id,
1234+
&counterparty_node_id,
1235+
)
1236+
.map_err(|e| {
1237+
log_error!(self.logger, "Failed to force-close channel: {:?}", e);
1238+
Error::ChannelClosingFailed
1239+
})?;
1240+
}
1241+
} else {
1242+
self.channel_manager
1243+
.close_channel(&channel_details.channel_id, &counterparty_node_id)
1244+
.map_err(|e| {
1245+
log_error!(self.logger, "Failed to close channel: {:?}", e);
1246+
Error::ChannelClosingFailed
1247+
})?;
1248+
}
1249+
1250+
// Check if this was the last open channel, if so, forget the peer.
1251+
if open_channels.len() == 1 {
1252+
self.peer_store.remove_peer(&counterparty_node_id)?;
11991253
}
1200-
} else {
1201-
Ok(())
12021254
}
1255+
1256+
Ok(())
12031257
}
12041258

12051259
/// Update the config for a previously opened channel.

0 commit comments

Comments
 (0)