diff --git a/ldk-server-cli/src/main.rs b/ldk-server-cli/src/main.rs index 3df55318..ed04e3be 100644 --- a/ldk-server-cli/src/main.rs +++ b/ldk-server-cli/src/main.rs @@ -231,15 +231,19 @@ enum Commands { CloseChannel { #[arg(help = "The local user_channel_id of this channel")] user_channel_id: String, - #[arg(help = "The hex-encoded public key of the node to close a channel with")] - counterparty_node_id: String, + #[arg( + help = "The hex-encoded public key of the node to close a channel with. If not provided, it will be looked up from the channel list" + )] + counterparty_node_id: Option, }, #[command(about = "Force close the channel specified by the given channel ID")] ForceCloseChannel { #[arg(help = "The local user_channel_id of this channel")] user_channel_id: String, - #[arg(help = "The hex-encoded public key of the node to close a channel with")] - counterparty_node_id: String, + #[arg( + help = "The hex-encoded public key of the node to close a channel with. If not provided, it will be looked up from the channel list" + )] + counterparty_node_id: Option, #[arg(long, help = "The reason for force-closing, defaults to \"\"")] force_close_reason: Option, }, @@ -339,9 +343,9 @@ enum Commands { #[arg(help = "The local user_channel_id of this channel")] user_channel_id: String, #[arg( - help = "The hex-encoded public key of the counterparty node to update channel config with" + help = "The hex-encoded public key of the counterparty node to update channel config with. If not provided, it will be looked up from the channel list" )] - counterparty_node_id: String, + counterparty_node_id: Option, #[arg( long, help = "Amount (in millionths of a satoshi) charged per satoshi for payments forwarded outbound over the channel. This can be updated by using update-channel-config." diff --git a/ldk-server-protos/src/api.rs b/ldk-server-protos/src/api.rs index b5b83bdf..2ac4b760 100644 --- a/ldk-server-protos/src/api.rs +++ b/ldk-server-protos/src/api.rs @@ -407,8 +407,9 @@ pub struct UpdateChannelConfigRequest { #[prost(string, tag = "1")] pub user_channel_id: ::prost::alloc::string::String, /// The hex-encoded public key of the counterparty node to update channel config with. - #[prost(string, tag = "2")] - pub counterparty_node_id: ::prost::alloc::string::String, + /// If not provided, it will be resolved from the channel list. + #[prost(string, optional, tag = "2")] + pub counterparty_node_id: ::core::option::Option<::prost::alloc::string::String>, /// The updated channel configuration settings for a channel. #[prost(message, optional, tag = "3")] pub channel_config: ::core::option::Option, @@ -431,8 +432,9 @@ pub struct CloseChannelRequest { #[prost(string, tag = "1")] pub user_channel_id: ::prost::alloc::string::String, /// The hex-encoded public key of the node to close a channel with. - #[prost(string, tag = "2")] - pub counterparty_node_id: ::prost::alloc::string::String, + /// If not provided, it will be resolved from the channel list. + #[prost(string, optional, tag = "2")] + pub counterparty_node_id: ::core::option::Option<::prost::alloc::string::String>, } /// The response `content` for the `CloseChannel` API, when HttpStatusCode is OK (200). /// When HttpStatusCode is not OK (non-200), the response `content` contains a serialized `ErrorResponse`. @@ -452,8 +454,9 @@ pub struct ForceCloseChannelRequest { #[prost(string, tag = "1")] pub user_channel_id: ::prost::alloc::string::String, /// The hex-encoded public key of the node to close a channel with. - #[prost(string, tag = "2")] - pub counterparty_node_id: ::prost::alloc::string::String, + /// If not provided, it will be resolved from the channel list. + #[prost(string, optional, tag = "2")] + pub counterparty_node_id: ::core::option::Option<::prost::alloc::string::String>, /// The reason for force-closing. #[prost(string, optional, tag = "3")] pub force_close_reason: ::core::option::Option<::prost::alloc::string::String>, diff --git a/ldk-server-protos/src/proto/api.proto b/ldk-server-protos/src/proto/api.proto index f4549d0a..375470cd 100644 --- a/ldk-server-protos/src/proto/api.proto +++ b/ldk-server-protos/src/proto/api.proto @@ -335,7 +335,8 @@ message UpdateChannelConfigRequest { string user_channel_id = 1; // The hex-encoded public key of the counterparty node to update channel config with. - string counterparty_node_id = 2; + // If not provided, it will be resolved from the channel list. + optional string counterparty_node_id = 2; // The updated channel configuration settings for a channel. types.ChannelConfig channel_config = 3; @@ -354,7 +355,8 @@ message CloseChannelRequest { string user_channel_id = 1; // The hex-encoded public key of the node to close a channel with. - string counterparty_node_id = 2; + // If not provided, it will be resolved from the channel list. + optional string counterparty_node_id = 2; } // The response `content` for the `CloseChannel` API, when HttpStatusCode is OK (200). @@ -367,7 +369,8 @@ message ForceCloseChannelRequest { // The local `user_channel_id` of this channel. string user_channel_id = 1; // The hex-encoded public key of the node to close a channel with. - string counterparty_node_id = 2; + // If not provided, it will be resolved from the channel list. + optional string counterparty_node_id = 2; // The reason for force-closing. optional string force_close_reason = 3; } diff --git a/ldk-server/src/api/close_channel.rs b/ldk-server/src/api/close_channel.rs index 5ae4070b..dbc02b48 100644 --- a/ldk-server/src/api/close_channel.rs +++ b/ldk-server/src/api/close_channel.rs @@ -23,7 +23,8 @@ pub(crate) fn handle_close_channel_request( context: Context, request: CloseChannelRequest, ) -> Result { let user_channel_id = parse_user_channel_id(&request.user_channel_id)?; - let counterparty_node_id = parse_counterparty_node_id(&request.counterparty_node_id)?; + let counterparty_node_id = + resolve_counterparty_node_id(&context, &user_channel_id, request.counterparty_node_id)?; context.node.close_channel(&user_channel_id, counterparty_node_id)?; @@ -34,7 +35,8 @@ pub(crate) fn handle_force_close_channel_request( context: Context, request: ForceCloseChannelRequest, ) -> Result { let user_channel_id = parse_user_channel_id(&request.user_channel_id)?; - let counterparty_node_id = parse_counterparty_node_id(&request.counterparty_node_id)?; + let counterparty_node_id = + resolve_counterparty_node_id(&context, &user_channel_id, request.counterparty_node_id)?; context.node.force_close_channel( &user_channel_id, @@ -60,3 +62,23 @@ fn parse_counterparty_node_id(id: &str) -> Result { ) }) } + +fn resolve_counterparty_node_id( + context: &Context, user_channel_id: &UserChannelId, counterparty_node_id: Option, +) -> Result { + match counterparty_node_id { + Some(id) => parse_counterparty_node_id(&id), + None => context + .node + .list_channels() + .into_iter() + .find(|c| c.user_channel_id == *user_channel_id) + .map(|c| c.counterparty_node_id) + .ok_or_else(|| { + LdkServerError::new( + InvalidRequestError, + "Channel not found for given user_channel_id.".to_string(), + ) + }), + } +} diff --git a/ldk-server/src/api/update_channel_config.rs b/ldk-server/src/api/update_channel_config.rs index 780374c5..cee421d3 100644 --- a/ldk-server/src/api/update_channel_config.rs +++ b/ldk-server/src/api/update_channel_config.rs @@ -26,30 +26,43 @@ pub(crate) fn handle_update_channel_config_request( .parse::() .map_err(|_| LdkServerError::new(InvalidRequestError, "Invalid UserChannelId."))?; - // FIXME: Use ldk/ldk-node's partial config update api. - let current_config = context + let channel = context .node .list_channels() .into_iter() .find(|c| c.user_channel_id.0 == user_channel_id) .ok_or_else(|| { LdkServerError::new(InvalidRequestError, "Channel not found for given user_channel_id.") - })? - .config; + })?; + // FIXME: Use ldk/ldk-node's partial config update api. let updated_channel_config = build_channel_config_from_proto( - current_config, + channel.config, request.channel_config.ok_or_else(|| { LdkServerError::new(InvalidRequestError, "Channel config must be provided.") })?, )?; - let counterparty_node_id = PublicKey::from_str(&request.counterparty_node_id).map_err(|e| { - LdkServerError::new( - InvalidRequestError, - format!("Invalid counterparty node id, error {}", e), - ) - })?; + let counterparty_node_id = match request.counterparty_node_id { + Some(id) => { + let node_id = PublicKey::from_str(&id).map_err(|e| { + LdkServerError::new( + InvalidRequestError, + format!("Invalid counterparty node id, error {}", e), + ) + })?; + + if node_id != channel.counterparty_node_id { + return Err(LdkServerError::new( + InvalidRequestError, + format!("Channel with user_channel_id {user_channel_id} is not connected to counterparty node id {node_id}."), + )); + } + + node_id + }, + None => channel.counterparty_node_id, + }; context .node