Skip to content

Commit ea448a1

Browse files
authored
Merge pull request #350 from tnull/2024-08-channel-config-refactor
Refactor `ChannelConfig` / `MaxDustHTLCExposure`
2 parents ab7cc70 + 09d68ee commit ea448a1

File tree

3 files changed

+118
-104
lines changed

3 files changed

+118
-104
lines changed

bindings/ldk_node.udl

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -409,20 +409,19 @@ dictionary BalanceDetails {
409409
sequence<PendingSweepBalance> pending_balances_from_channel_closures;
410410
};
411411

412-
interface ChannelConfig {
413-
constructor();
414-
u32 forwarding_fee_proportional_millionths();
415-
void set_forwarding_fee_proportional_millionths(u32 value);
416-
u32 forwarding_fee_base_msat();
417-
void set_forwarding_fee_base_msat(u32 fee_msat);
418-
u16 cltv_expiry_delta();
419-
void set_cltv_expiry_delta(u16 value);
420-
u64 force_close_avoidance_max_fee_satoshis();
421-
void set_force_close_avoidance_max_fee_satoshis(u64 value_sat);
422-
boolean accept_underpaying_htlcs();
423-
void set_accept_underpaying_htlcs(boolean value);
424-
void set_max_dust_htlc_exposure_from_fixed_limit(u64 limit_msat);
425-
void set_max_dust_htlc_exposure_from_fee_rate_multiplier(u64 multiplier);
412+
dictionary ChannelConfig {
413+
u32 forwarding_fee_proportional_millionths;
414+
u32 forwarding_fee_base_msat;
415+
u16 cltv_expiry_delta;
416+
MaxDustHTLCExposure max_dust_htlc_exposure;
417+
u64 force_close_avoidance_max_fee_satoshis;
418+
boolean accept_underpaying_htlcs;
419+
};
420+
421+
[Enum]
422+
interface MaxDustHTLCExposure {
423+
FixedLimit ( u64 limit_msat );
424+
FeeRateMultiplier ( u64 multiplier );
426425
};
427426

428427
enum LogLevel {

src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub use error::Error as NodeError;
109109
use error::Error;
110110

111111
pub use event::Event;
112-
pub use types::ChannelConfig;
112+
pub use types::{ChannelConfig, MaxDustHTLCExposure};
113113

114114
pub use io::utils::generate_entropy_mnemonic;
115115

@@ -1187,7 +1187,7 @@ impl Node {
11871187
/// Returns a [`UserChannelId`] allowing to locally keep track of the channel.
11881188
pub fn connect_open_channel(
11891189
&self, node_id: PublicKey, address: SocketAddress, channel_amount_sats: u64,
1190-
push_to_counterparty_msat: Option<u64>, channel_config: Option<Arc<ChannelConfig>>,
1190+
push_to_counterparty_msat: Option<u64>, channel_config: Option<ChannelConfig>,
11911191
announce_channel: bool,
11921192
) -> Result<UserChannelId, Error> {
11931193
let rt_lock = self.runtime.read().unwrap();
@@ -1251,7 +1251,7 @@ impl Node {
12511251

12521252
let mut user_config = default_user_config(&self.config);
12531253
user_config.channel_handshake_config.announced_channel = announce_channel;
1254-
user_config.channel_config = (*(channel_config.unwrap_or_default())).clone().into();
1254+
user_config.channel_config = (channel_config.unwrap_or_default()).clone().into();
12551255
// We set the max inflight to 100% for private channels.
12561256
// FIXME: LDK will default to this behavior soon, too, at which point we should drop this
12571257
// manual override.
@@ -1494,7 +1494,7 @@ impl Node {
14941494
/// Update the config for a previously opened channel.
14951495
pub fn update_channel_config(
14961496
&self, user_channel_id: &UserChannelId, counterparty_node_id: PublicKey,
1497-
channel_config: Arc<ChannelConfig>,
1497+
channel_config: ChannelConfig,
14981498
) -> Result<(), Error> {
14991499
let open_channels =
15001500
self.channel_manager.list_channels_with_counterparty(&counterparty_node_id);
@@ -1505,7 +1505,7 @@ impl Node {
15051505
.update_channel_config(
15061506
&counterparty_node_id,
15071507
&[channel_details.channel_id],
1508-
&(*channel_config).clone().into(),
1508+
&(channel_config).clone().into(),
15091509
)
15101510
.map_err(|_| Error::ChannelConfigUpdateFailed)
15111511
} else {

src/types.rs

Lines changed: 100 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use lightning_transaction_sync::EsploraSyncClient;
2222
use bitcoin::secp256k1::PublicKey;
2323
use bitcoin::OutPoint;
2424

25-
use std::sync::{Arc, Mutex, RwLock};
25+
use std::sync::{Arc, Mutex};
2626

2727
pub(crate) type DynStore = dyn KVStore + Sync + Send;
2828

@@ -279,7 +279,7 @@ pub struct ChannelDetails {
279279
/// The largest value HTLC (in msat) we currently will accept, for this channel.
280280
pub inbound_htlc_maximum_msat: Option<u64>,
281281
/// Set of configurable parameters that affect channel operation.
282-
pub config: Arc<ChannelConfig>,
282+
pub config: ChannelConfig,
283283
}
284284

285285
impl From<LdkChannelDetails> for ChannelDetails {
@@ -330,7 +330,7 @@ impl From<LdkChannelDetails> for ChannelDetails {
330330
inbound_htlc_minimum_msat: value.inbound_htlc_minimum_msat.unwrap_or(0),
331331
inbound_htlc_maximum_msat: value.inbound_htlc_maximum_msat,
332332
// unwrap safety: `config` is only `None` for LDK objects serialized prior to 0.0.109.
333-
config: value.config.map(|c| Arc::new(c.into())).unwrap(),
333+
config: value.config.map(|c| c.into()).unwrap(),
334334
}
335335
}
336336
}
@@ -350,98 +350,70 @@ pub struct PeerDetails {
350350
pub is_connected: bool,
351351
}
352352

353-
/// Options which apply on a per-channel basis.
354-
///
355-
/// See documentation of [`LdkChannelConfig`] for details.
356-
#[derive(Debug)]
353+
/// Options which apply on a per-channel basis and may change at runtime or based on negotiation
354+
/// with our counterparty.
355+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
357356
pub struct ChannelConfig {
358-
inner: RwLock<LdkChannelConfig>,
359-
}
360-
361-
impl Clone for ChannelConfig {
362-
fn clone(&self) -> Self {
363-
self.inner.read().unwrap().clone().into()
364-
}
365-
}
366-
367-
impl ChannelConfig {
368-
/// Constructs a new `ChannelConfig`.
369-
pub fn new() -> Self {
370-
Self::default()
371-
}
372-
373-
/// Returns the set `forwarding_fee_proportional_millionths`.
374-
pub fn forwarding_fee_proportional_millionths(&self) -> u32 {
375-
self.inner.read().unwrap().forwarding_fee_proportional_millionths
376-
}
377-
378-
/// Sets the `forwarding_fee_proportional_millionths`.
379-
pub fn set_forwarding_fee_proportional_millionths(&self, value: u32) {
380-
self.inner.write().unwrap().forwarding_fee_proportional_millionths = value;
381-
}
382-
383-
/// Returns the set `forwarding_fee_base_msat`.
384-
pub fn forwarding_fee_base_msat(&self) -> u32 {
385-
self.inner.read().unwrap().forwarding_fee_base_msat
386-
}
387-
388-
/// Sets the `forwarding_fee_base_msat`.
389-
pub fn set_forwarding_fee_base_msat(&self, fee_msat: u32) {
390-
self.inner.write().unwrap().forwarding_fee_base_msat = fee_msat;
391-
}
392-
393-
/// Returns the set `cltv_expiry_delta`.
394-
pub fn cltv_expiry_delta(&self) -> u16 {
395-
self.inner.read().unwrap().cltv_expiry_delta
396-
}
397-
398-
/// Sets the `cltv_expiry_delta`.
399-
pub fn set_cltv_expiry_delta(&self, value: u16) {
400-
self.inner.write().unwrap().cltv_expiry_delta = value;
401-
}
402-
403-
/// Returns the set `force_close_avoidance_max_fee_satoshis`.
404-
pub fn force_close_avoidance_max_fee_satoshis(&self) -> u64 {
405-
self.inner.read().unwrap().force_close_avoidance_max_fee_satoshis
406-
}
407-
408-
/// Sets the `force_close_avoidance_max_fee_satoshis`.
409-
pub fn set_force_close_avoidance_max_fee_satoshis(&self, value_sat: u64) {
410-
self.inner.write().unwrap().force_close_avoidance_max_fee_satoshis = value_sat;
411-
}
412-
413-
/// Returns the set `accept_underpaying_htlcs`.
414-
pub fn accept_underpaying_htlcs(&self) -> bool {
415-
self.inner.read().unwrap().accept_underpaying_htlcs
416-
}
417-
418-
/// Sets the `accept_underpaying_htlcs`.
419-
pub fn set_accept_underpaying_htlcs(&self, value: bool) {
420-
self.inner.write().unwrap().accept_underpaying_htlcs = value;
421-
}
422-
423-
/// Sets the `max_dust_htlc_exposure` from a fixed limit.
424-
pub fn set_max_dust_htlc_exposure_from_fixed_limit(&self, limit_msat: u64) {
425-
self.inner.write().unwrap().max_dust_htlc_exposure =
426-
LdkMaxDustHTLCExposure::FixedLimitMsat(limit_msat);
427-
}
428-
429-
/// Sets the `max_dust_htlc_exposure` from a fee rate multiplier.
430-
pub fn set_max_dust_htlc_exposure_from_fee_rate_multiplier(&self, multiplier: u64) {
431-
self.inner.write().unwrap().max_dust_htlc_exposure =
432-
LdkMaxDustHTLCExposure::FeeRateMultiplier(multiplier);
433-
}
357+
/// Amount (in millionths of a satoshi) charged per satoshi for payments forwarded outbound
358+
/// over the channel.
359+
/// This may be allowed to change at runtime in a later update, however doing so must result in
360+
/// update messages sent to notify all nodes of our updated relay fee.
361+
///
362+
/// Please refer to [`LdkChannelConfig`] for further details.
363+
pub forwarding_fee_proportional_millionths: u32,
364+
/// Amount (in milli-satoshi) charged for payments forwarded outbound over the channel, in
365+
/// excess of [`ChannelConfig::forwarding_fee_proportional_millionths`].
366+
/// This may be allowed to change at runtime in a later update, however doing so must result in
367+
/// update messages sent to notify all nodes of our updated relay fee.
368+
///
369+
/// Please refer to [`LdkChannelConfig`] for further details.
370+
pub forwarding_fee_base_msat: u32,
371+
/// The difference in the CLTV value between incoming HTLCs and an outbound HTLC forwarded over
372+
/// the channel this config applies to.
373+
///
374+
/// Please refer to [`LdkChannelConfig`] for further details.
375+
pub cltv_expiry_delta: u16,
376+
/// Limit our total exposure to potential loss to on-chain fees on close, including in-flight
377+
/// HTLCs which are burned to fees as they are too small to claim on-chain and fees on
378+
/// commitment transaction(s) broadcasted by our counterparty in excess of our own fee estimate.
379+
///
380+
/// Please refer to [`LdkChannelConfig`] for further details.
381+
pub max_dust_htlc_exposure: MaxDustHTLCExposure,
382+
/// The additional fee we're willing to pay to avoid waiting for the counterparty's
383+
/// `to_self_delay` to reclaim funds.
384+
///
385+
/// Please refer to [`LdkChannelConfig`] for further details.
386+
pub force_close_avoidance_max_fee_satoshis: u64,
387+
/// If set, allows this channel's counterparty to skim an additional fee off this node's inbound
388+
/// HTLCs. Useful for liquidity providers to offload on-chain channel costs to end users.
389+
///
390+
/// Please refer to [`LdkChannelConfig`] for further details.
391+
pub accept_underpaying_htlcs: bool,
434392
}
435393

436394
impl From<LdkChannelConfig> for ChannelConfig {
437395
fn from(value: LdkChannelConfig) -> Self {
438-
Self { inner: RwLock::new(value) }
396+
Self {
397+
forwarding_fee_proportional_millionths: value.forwarding_fee_proportional_millionths,
398+
forwarding_fee_base_msat: value.forwarding_fee_base_msat,
399+
cltv_expiry_delta: value.cltv_expiry_delta,
400+
max_dust_htlc_exposure: value.max_dust_htlc_exposure.into(),
401+
force_close_avoidance_max_fee_satoshis: value.force_close_avoidance_max_fee_satoshis,
402+
accept_underpaying_htlcs: value.accept_underpaying_htlcs,
403+
}
439404
}
440405
}
441406

442407
impl From<ChannelConfig> for LdkChannelConfig {
443408
fn from(value: ChannelConfig) -> Self {
444-
*value.inner.read().unwrap()
409+
Self {
410+
forwarding_fee_proportional_millionths: value.forwarding_fee_proportional_millionths,
411+
forwarding_fee_base_msat: value.forwarding_fee_base_msat,
412+
cltv_expiry_delta: value.cltv_expiry_delta,
413+
max_dust_htlc_exposure: value.max_dust_htlc_exposure.into(),
414+
force_close_avoidance_max_fee_satoshis: value.force_close_avoidance_max_fee_satoshis,
415+
accept_underpaying_htlcs: value.accept_underpaying_htlcs,
416+
}
445417
}
446418
}
447419

@@ -450,3 +422,46 @@ impl Default for ChannelConfig {
450422
LdkChannelConfig::default().into()
451423
}
452424
}
425+
426+
/// Options for how to set the max dust exposure allowed on a channel.
427+
///
428+
/// See [`LdkChannelConfig::max_dust_htlc_exposure`] for details.
429+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
430+
pub enum MaxDustHTLCExposure {
431+
/// This sets a fixed limit on the total dust exposure in millisatoshis.
432+
///
433+
/// Please refer to [`LdkMaxDustHTLCExposure`] for further details.
434+
FixedLimit {
435+
/// The fixed limit, in millisatoshis.
436+
limit_msat: u64,
437+
},
438+
/// This sets a multiplier on the feerate to determine the maximum allowed dust exposure.
439+
///
440+
/// Please refer to [`LdkMaxDustHTLCExposure`] for further details.
441+
FeeRateMultiplier {
442+
/// The applied fee rate multiplier.
443+
multiplier: u64,
444+
},
445+
}
446+
447+
impl From<LdkMaxDustHTLCExposure> for MaxDustHTLCExposure {
448+
fn from(value: LdkMaxDustHTLCExposure) -> Self {
449+
match value {
450+
LdkMaxDustHTLCExposure::FixedLimitMsat(limit_msat) => Self::FixedLimit { limit_msat },
451+
LdkMaxDustHTLCExposure::FeeRateMultiplier(multiplier) => {
452+
Self::FeeRateMultiplier { multiplier }
453+
},
454+
}
455+
}
456+
}
457+
458+
impl From<MaxDustHTLCExposure> for LdkMaxDustHTLCExposure {
459+
fn from(value: MaxDustHTLCExposure) -> Self {
460+
match value {
461+
MaxDustHTLCExposure::FixedLimit { limit_msat } => Self::FixedLimitMsat(limit_msat),
462+
MaxDustHTLCExposure::FeeRateMultiplier { multiplier } => {
463+
Self::FeeRateMultiplier(multiplier)
464+
},
465+
}
466+
}
467+
}

0 commit comments

Comments
 (0)