Skip to content

Commit 0d02e50

Browse files
authored
Merge pull request #81 from benthecarman/open-channel-cfg
Hook up ChannelConfig in open channel endpoint & add to cli
2 parents 2c24f68 + 22cae11 commit 0d02e50

4 files changed

Lines changed: 110 additions & 52 deletions

File tree

ldk-server-cli/src/main.rs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ use ldk_server_client::ldk_server_protos::api::{
1111
OpenChannelRequest, SpliceInRequest, SpliceOutRequest,
1212
};
1313
use ldk_server_client::ldk_server_protos::types::{
14-
bolt11_invoice_description, Bolt11InvoiceDescription, PageToken, Payment,
14+
bolt11_invoice_description, channel_config, Bolt11InvoiceDescription, ChannelConfig, PageToken,
15+
Payment,
1516
};
1617
use std::fmt::Debug;
1718

@@ -101,6 +102,22 @@ enum Commands {
101102
push_to_counterparty_msat: Option<u64>,
102103
#[arg(long)]
103104
announce_channel: bool,
105+
// Channel config options
106+
#[arg(
107+
long,
108+
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."
109+
)]
110+
forwarding_fee_proportional_millionths: Option<u32>,
111+
#[arg(
112+
long,
113+
help = "Amount (in milli-satoshi) charged for payments forwarded outbound over the channel, in excess of forwarding_fee_proportional_millionths. This can be updated by using update-channel-config."
114+
)]
115+
forwarding_fee_base_msat: Option<u32>,
116+
#[arg(
117+
long,
118+
help = "The difference in the CLTV value between incoming HTLCs and an outbound HTLC forwarded over the channel. This can be updated by using update-channel-config."
119+
)]
120+
cltv_expiry_delta: Option<u32>,
104121
},
105122
SpliceIn {
106123
#[arg(short, long)]
@@ -231,15 +248,24 @@ async fn main() {
231248
channel_amount_sats,
232249
push_to_counterparty_msat,
233250
announce_channel,
251+
forwarding_fee_proportional_millionths,
252+
forwarding_fee_base_msat,
253+
cltv_expiry_delta,
234254
} => {
255+
let channel_config = build_open_channel_config(
256+
forwarding_fee_proportional_millionths,
257+
forwarding_fee_base_msat,
258+
cltv_expiry_delta,
259+
);
260+
235261
handle_response_result(
236262
client
237263
.open_channel(OpenChannelRequest {
238264
node_pubkey,
239265
address,
240266
channel_amount_sats,
241267
push_to_counterparty_msat,
242-
channel_config: None,
268+
channel_config,
243269
announce_channel,
244270
})
245271
.await,
@@ -282,6 +308,28 @@ async fn main() {
282308
}
283309
}
284310

311+
fn build_open_channel_config(
312+
forwarding_fee_proportional_millionths: Option<u32>, forwarding_fee_base_msat: Option<u32>,
313+
cltv_expiry_delta: Option<u32>,
314+
) -> Option<ChannelConfig> {
315+
// Only create a config if at least one field is set
316+
if forwarding_fee_proportional_millionths.is_none()
317+
&& forwarding_fee_base_msat.is_none()
318+
&& cltv_expiry_delta.is_none()
319+
{
320+
return None;
321+
}
322+
323+
Some(ChannelConfig {
324+
forwarding_fee_proportional_millionths,
325+
forwarding_fee_base_msat,
326+
cltv_expiry_delta,
327+
force_close_avoidance_max_fee_satoshis: None,
328+
accept_underpaying_htlcs: None,
329+
max_dust_htlc_exposure: None,
330+
})
331+
}
332+
285333
async fn list_n_payments(
286334
client: LdkServerClient, number_of_payments: Option<u64>,
287335
) -> Result<Vec<Payment>, LdkServerError> {

ldk-server/src/api/mod.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
use crate::api::error::LdkServerError;
2+
use crate::api::error::LdkServerErrorCode::InvalidRequestError;
3+
use ldk_node::config::{ChannelConfig, MaxDustHTLCExposure};
4+
use ldk_server_protos::types::channel_config::MaxDustHtlcExposure;
5+
16
pub(crate) mod bolt11_receive;
27
pub(crate) mod bolt11_send;
38
pub(crate) mod bolt12_receive;
@@ -15,3 +20,47 @@ pub(crate) mod onchain_send;
1520
pub(crate) mod open_channel;
1621
pub(crate) mod splice_channel;
1722
pub(crate) mod update_channel_config;
23+
24+
pub(crate) fn build_channel_config_from_proto(
25+
default_config: ChannelConfig, proto_channel_config: ldk_server_protos::types::ChannelConfig,
26+
) -> Result<ChannelConfig, LdkServerError> {
27+
let max_dust_htlc_exposure = proto_channel_config
28+
.max_dust_htlc_exposure
29+
.map(|max_dust_htlc_exposure| match max_dust_htlc_exposure {
30+
MaxDustHtlcExposure::FixedLimitMsat(limit_msat) => {
31+
MaxDustHTLCExposure::FixedLimit { limit_msat }
32+
},
33+
MaxDustHtlcExposure::FeeRateMultiplier(multiplier) => {
34+
MaxDustHTLCExposure::FeeRateMultiplier { multiplier }
35+
},
36+
})
37+
.unwrap_or(default_config.max_dust_htlc_exposure);
38+
39+
let cltv_expiry_delta = match proto_channel_config.cltv_expiry_delta {
40+
Some(c) => Some(u16::try_from(c).map_err(|_| {
41+
LdkServerError::new(
42+
InvalidRequestError,
43+
format!("Invalid cltv_expiry_delta, must be between 0 and {}", u16::MAX),
44+
)
45+
})?),
46+
None => None,
47+
}
48+
.unwrap_or(default_config.cltv_expiry_delta);
49+
50+
Ok(ChannelConfig {
51+
forwarding_fee_proportional_millionths: proto_channel_config
52+
.forwarding_fee_proportional_millionths
53+
.unwrap_or(default_config.forwarding_fee_proportional_millionths),
54+
forwarding_fee_base_msat: proto_channel_config
55+
.forwarding_fee_base_msat
56+
.unwrap_or(default_config.forwarding_fee_base_msat),
57+
cltv_expiry_delta,
58+
max_dust_htlc_exposure,
59+
force_close_avoidance_max_fee_satoshis: proto_channel_config
60+
.force_close_avoidance_max_fee_satoshis
61+
.unwrap_or(default_config.force_close_avoidance_max_fee_satoshis),
62+
accept_underpaying_htlcs: proto_channel_config
63+
.accept_underpaying_htlcs
64+
.unwrap_or(default_config.accept_underpaying_htlcs),
65+
})
66+
}

ldk-server/src/api/open_channel.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
use crate::api::build_channel_config_from_proto;
12
use crate::api::error::LdkServerError;
23
use crate::service::Context;
34
use ldk_node::bitcoin::secp256k1::PublicKey;
5+
use ldk_node::config::ChannelConfig;
46
use ldk_node::lightning::ln::msgs::SocketAddress;
57
use ldk_server_protos::api::{OpenChannelRequest, OpenChannelResponse};
68
use std::str::FromStr;
@@ -13,22 +15,26 @@ pub(crate) fn handle_open_channel(
1315
let address = SocketAddress::from_str(&request.address)
1416
.map_err(|_| ldk_node::NodeError::InvalidSocketAddress)?;
1517

18+
let channel_config = request
19+
.channel_config
20+
.map(|proto_config| build_channel_config_from_proto(ChannelConfig::default(), proto_config))
21+
.transpose()?;
22+
1623
let user_channel_id = if request.announce_channel {
1724
context.node.open_announced_channel(
1825
node_id,
1926
address,
2027
request.channel_amount_sats,
2128
request.push_to_counterparty_msat,
22-
// TODO: Allow setting ChannelConfig in open-channel.
23-
None,
29+
channel_config,
2430
)?
2531
} else {
2632
context.node.open_channel(
2733
node_id,
2834
address,
2935
request.channel_amount_sats,
3036
request.push_to_counterparty_msat,
31-
None,
37+
channel_config,
3238
)?
3339
};
3440

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1+
use crate::api::build_channel_config_from_proto;
12
use crate::api::error::LdkServerError;
23
use crate::api::error::LdkServerErrorCode::{InvalidRequestError, LightningError};
34
use crate::service::Context;
45
use ldk_node::bitcoin::secp256k1::PublicKey;
5-
use ldk_node::config::{ChannelConfig, MaxDustHTLCExposure};
66
use ldk_node::UserChannelId;
77
use ldk_server_protos::api::{UpdateChannelConfigRequest, UpdateChannelConfigResponse};
8-
use ldk_server_protos::types::channel_config::MaxDustHtlcExposure;
98
use std::str::FromStr;
109

1110
pub(crate) fn handle_update_channel_config_request(
@@ -27,7 +26,7 @@ pub(crate) fn handle_update_channel_config_request(
2726
})?
2827
.config;
2928

30-
let updated_channel_config = build_updated_channel_config(
29+
let updated_channel_config = build_channel_config_from_proto(
3130
current_config,
3231
request.channel_config.ok_or_else(|| {
3332
LdkServerError::new(InvalidRequestError, "Channel config must be provided.")
@@ -54,47 +53,3 @@ pub(crate) fn handle_update_channel_config_request(
5453

5554
Ok(UpdateChannelConfigResponse {})
5655
}
57-
58-
fn build_updated_channel_config(
59-
current_config: ChannelConfig, proto_channel_config: ldk_server_protos::types::ChannelConfig,
60-
) -> Result<ChannelConfig, LdkServerError> {
61-
let max_dust_htlc_exposure = proto_channel_config
62-
.max_dust_htlc_exposure
63-
.map(|max_dust_htlc_exposure| match max_dust_htlc_exposure {
64-
MaxDustHtlcExposure::FixedLimitMsat(limit_msat) => {
65-
MaxDustHTLCExposure::FixedLimit { limit_msat }
66-
},
67-
MaxDustHtlcExposure::FeeRateMultiplier(multiplier) => {
68-
MaxDustHTLCExposure::FeeRateMultiplier { multiplier }
69-
},
70-
})
71-
.unwrap_or(current_config.max_dust_htlc_exposure);
72-
73-
let cltv_expiry_delta = match proto_channel_config.cltv_expiry_delta {
74-
Some(c) => Some(u16::try_from(c).map_err(|_| {
75-
LdkServerError::new(
76-
InvalidRequestError,
77-
format!("Invalid cltv_expiry_delta, must be between 0 and {}", u16::MAX),
78-
)
79-
})?),
80-
None => None,
81-
}
82-
.unwrap_or_else(|| current_config.cltv_expiry_delta);
83-
84-
Ok(ChannelConfig {
85-
forwarding_fee_proportional_millionths: proto_channel_config
86-
.forwarding_fee_proportional_millionths
87-
.unwrap_or(current_config.forwarding_fee_proportional_millionths),
88-
forwarding_fee_base_msat: proto_channel_config
89-
.forwarding_fee_base_msat
90-
.unwrap_or(current_config.forwarding_fee_base_msat),
91-
cltv_expiry_delta,
92-
max_dust_htlc_exposure,
93-
force_close_avoidance_max_fee_satoshis: proto_channel_config
94-
.force_close_avoidance_max_fee_satoshis
95-
.unwrap_or(current_config.force_close_avoidance_max_fee_satoshis),
96-
accept_underpaying_htlcs: proto_channel_config
97-
.accept_underpaying_htlcs
98-
.unwrap_or(current_config.accept_underpaying_htlcs),
99-
})
100-
}

0 commit comments

Comments
 (0)