Skip to content

Commit 889e0a3

Browse files
Add force_close_channel API endpoint and handler
Introduce ForceCloseChannelRequest and ForceCloseChannelResponse to the API, implement the handle_force_close_channel_request function, and register the new endpoint in the service router.
1 parent 2c926ae commit 889e0a3

File tree

4 files changed

+80
-12
lines changed

4 files changed

+80
-12
lines changed

ldk-server-protos/src/api.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,26 @@ pub struct CloseChannelRequest {
286286
#[allow(clippy::derive_partial_eq_without_eq)]
287287
#[derive(Clone, PartialEq, ::prost::Message)]
288288
pub struct CloseChannelResponse {}
289+
/// Force closes the channel specified by given request.
290+
/// See more: <https://docs.rs/ldk-node/latest/ldk_node/struct.Node.html#method.force_close_channel>
291+
#[allow(clippy::derive_partial_eq_without_eq)]
292+
#[derive(Clone, PartialEq, ::prost::Message)]
293+
pub struct ForceCloseChannelRequest {
294+
/// The local `user_channel_id` of this channel.
295+
#[prost(string, tag = "1")]
296+
pub user_channel_id: ::prost::alloc::string::String,
297+
/// The hex-encoded public key of the node to close a channel with.
298+
#[prost(string, tag = "2")]
299+
pub counterparty_node_id: ::prost::alloc::string::String,
300+
/// The reason for force-closing.
301+
#[prost(string, optional, tag = "3")]
302+
pub force_close_reason: ::core::option::Option<::prost::alloc::string::String>,
303+
}
304+
/// The response `content` for the `ForceCloseChannel` API, when HttpStatusCode is OK (200).
305+
/// When HttpStatusCode is not OK (non-200), the response `content` contains a serialized `ErrorResponse`.
306+
#[allow(clippy::derive_partial_eq_without_eq)]
307+
#[derive(Clone, PartialEq, ::prost::Message)]
308+
pub struct ForceCloseChannelResponse {}
289309
/// Returns a list of known channels.
290310
/// See more: <https://docs.rs/ldk-node/latest/ldk_node/struct.Node.html#method.list_channels>
291311
#[allow(clippy::derive_partial_eq_without_eq)]

ldk-server-protos/src/proto/api.proto

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,21 @@ message CloseChannelRequest {
275275
// When HttpStatusCode is not OK (non-200), the response `content` contains a serialized `ErrorResponse`.
276276
message CloseChannelResponse {}
277277

278+
// Force closes the channel specified by given request.
279+
// See more: https://docs.rs/ldk-node/latest/ldk_node/struct.Node.html#method.force_close_channel
280+
message ForceCloseChannelRequest {
281+
// The local `user_channel_id` of this channel.
282+
string user_channel_id = 1;
283+
// The hex-encoded public key of the node to close a channel with.
284+
string counterparty_node_id = 2;
285+
// The reason for force-closing.
286+
optional string force_close_reason = 3;
287+
}
288+
289+
// The response `content` for the `ForceCloseChannel` API, when HttpStatusCode is OK (200).
290+
// When HttpStatusCode is not OK (non-200), the response `content` contains a serialized `ErrorResponse`.
291+
message ForceCloseChannelResponse {}
292+
278293
// Returns a list of known channels.
279294
// See more: https://docs.rs/ldk-node/latest/ldk_node/struct.Node.html#method.list_channels
280295
message ListChannelsRequest {}

ldk-server/src/api/close_channel.rs

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,53 @@ use crate::api::error::LdkServerErrorCode::InvalidRequestError;
33
use crate::service::Context;
44
use ldk_node::bitcoin::secp256k1::PublicKey;
55
use ldk_node::UserChannelId;
6-
use ldk_server_protos::api::{CloseChannelRequest, CloseChannelResponse};
6+
use ldk_server_protos::api::{
7+
CloseChannelRequest, CloseChannelResponse, ForceCloseChannelRequest, ForceCloseChannelResponse,
8+
};
79
use std::str::FromStr;
810

911
pub(crate) const CLOSE_CHANNEL_PATH: &str = "CloseChannel";
1012

1113
pub(crate) fn handle_close_channel_request(
1214
context: Context, request: CloseChannelRequest,
1315
) -> Result<CloseChannelResponse, LdkServerError> {
14-
let user_channel_id =
15-
UserChannelId((&request.user_channel_id).parse::<u128>().map_err(|_| {
16-
LdkServerError::new(InvalidRequestError, "Invalid UserChannelId.".to_string())
17-
})?);
18-
let counterparty_node_id = PublicKey::from_str(&request.counterparty_node_id).map_err(|e| {
16+
let user_channel_id = parse_user_channel_id(&request.user_channel_id)?;
17+
let counterparty_node_id = parse_counterparty_node_id(&request.counterparty_node_id)?;
18+
19+
context.node.close_channel(&user_channel_id, counterparty_node_id)?;
20+
21+
Ok(CloseChannelResponse {})
22+
}
23+
24+
pub(crate) const FORCE_CLOSE_CHANNEL_PATH: &str = "ForceCloseChannel";
25+
26+
pub(crate) fn handle_force_close_channel_request(
27+
context: Context, request: ForceCloseChannelRequest,
28+
) -> Result<ForceCloseChannelResponse, LdkServerError> {
29+
let user_channel_id = parse_user_channel_id(&request.user_channel_id)?;
30+
let counterparty_node_id = parse_counterparty_node_id(&request.counterparty_node_id)?;
31+
32+
context.node.force_close_channel(
33+
&user_channel_id,
34+
counterparty_node_id,
35+
request.force_close_reason,
36+
)?;
37+
38+
Ok(ForceCloseChannelResponse {})
39+
}
40+
41+
fn parse_user_channel_id(id: &str) -> Result<UserChannelId, LdkServerError> {
42+
let parsed = id.parse::<u128>().map_err(|_| {
43+
LdkServerError::new(InvalidRequestError, "Invalid UserChannelId.".to_string())
44+
})?;
45+
Ok(UserChannelId(parsed))
46+
}
47+
48+
fn parse_counterparty_node_id(id: &str) -> Result<PublicKey, LdkServerError> {
49+
PublicKey::from_str(id).map_err(|e| {
1950
LdkServerError::new(
2051
InvalidRequestError,
2152
format!("Invalid counterparty node ID, error: {}", e),
2253
)
23-
})?;
24-
context.node.close_channel(&user_channel_id, counterparty_node_id)?;
25-
26-
let response = CloseChannelResponse {};
27-
Ok(response)
54+
})
2855
}

ldk-server/src/service.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ use crate::api::bolt11_receive::{handle_bolt11_receive_request, BOLT11_RECEIVE_P
1111
use crate::api::bolt11_send::{handle_bolt11_send_request, BOLT11_SEND_PATH};
1212
use crate::api::bolt12_receive::{handle_bolt12_receive_request, BOLT12_RECEIVE_PATH};
1313
use crate::api::bolt12_send::{handle_bolt12_send_request, BOLT12_SEND_PATH};
14-
use crate::api::close_channel::{handle_close_channel_request, CLOSE_CHANNEL_PATH};
14+
use crate::api::close_channel::{
15+
handle_close_channel_request, handle_force_close_channel_request, CLOSE_CHANNEL_PATH,
16+
FORCE_CLOSE_CHANNEL_PATH,
17+
};
1518
use crate::api::error::LdkServerError;
1619
use crate::api::error::LdkServerErrorCode::InvalidRequestError;
1720
use crate::api::get_balances::{handle_get_balances_request, GET_BALANCES};
@@ -85,6 +88,9 @@ impl Service<Request<Incoming>> for NodeService {
8588
CLOSE_CHANNEL_PATH => {
8689
Box::pin(handle_request(context, req, handle_close_channel_request))
8790
},
91+
FORCE_CLOSE_CHANNEL_PATH => {
92+
Box::pin(handle_request(context, req, handle_force_close_channel_request))
93+
},
8894
LIST_CHANNELS_PATH => {
8995
Box::pin(handle_request(context, req, handle_list_channels_request))
9096
},

0 commit comments

Comments
 (0)