Skip to content

Commit a8dd213

Browse files
committed
Add max dust exposure multiplier config knob
With fee rates rising dramatically in mid-April 2023, thresholds for what is considered dust have risen, often exceeding our previous dust exposure threshold of 5k sats. This causes all payments and HTLC forwards between 5k sats and new dust thresholds to fail. This commit adds a config knob that will allow us to implement setting our max dust exposure limit to the product of a multiplier and the high priority feerate.
1 parent c3c1050 commit a8dd213

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

lightning/src/util/config.rs

+27
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,21 @@ pub struct ChannelConfig {
397397
/// [`Normal`]: crate::chain::chaininterface::ConfirmationTarget::Normal
398398
/// [`Background`]: crate::chain::chaininterface::ConfirmationTarget::Background
399399
pub force_close_avoidance_max_fee_satoshis: u64,
400+
/// Similar to [`Self::max_dust_htlc_exposure_msat`], but instead of setting a fixed maximum,
401+
/// this sets a multiplier on the estimated high priority feerate (sats/KW, as obtained from
402+
/// [`FeeEstimator`]) to determine the maximum allowed dust exposure. If this field is set to
403+
/// `Some(value)`, then the maximum dust exposure in sats is calculated as:
404+
/// `high_priority_feerate_per_kw * value / 1000`.
405+
///
406+
/// This allows the maximum dust exposure to automatically scale with fee rate changes. With
407+
/// a fixed maximum, if the feerate increases significantly, then without a manually increase
408+
/// to this maximum, the channel may be unable to send/receive HTLCs between the maximum dust
409+
/// exposure and the new minimum value for HTLCs to be economically viable to claim.
410+
///
411+
/// Default value: `Some(5000)`.
412+
///
413+
/// [`FeeEstimator`]: crate::chain::chaininterface::FeeEstimator
414+
pub max_dust_htlc_exposure_multiplier_thousandths: Option<u64>,
400415
}
401416

402417
impl ChannelConfig {
@@ -417,6 +432,9 @@ impl ChannelConfig {
417432
if let Some(force_close_avoidance_max_fee_satoshis) = update.force_close_avoidance_max_fee_satoshis {
418433
self.force_close_avoidance_max_fee_satoshis = force_close_avoidance_max_fee_satoshis;
419434
}
435+
if let Some(max_dust_htlc_exposure_multiplier_thousandths) = update.max_dust_htlc_exposure_multiplier_thousandths {
436+
self.max_dust_htlc_exposure_multiplier_thousandths = max_dust_htlc_exposure_multiplier_thousandths;
437+
}
420438
}
421439
}
422440

@@ -429,6 +447,7 @@ impl Default for ChannelConfig {
429447
cltv_expiry_delta: 6 * 12, // 6 blocks/hour * 12 hours
430448
max_dust_htlc_exposure_msat: 5_000_000,
431449
force_close_avoidance_max_fee_satoshis: 1000,
450+
max_dust_htlc_exposure_multiplier_thousandths: Some(5000),
432451
}
433452
}
434453
}
@@ -442,6 +461,7 @@ impl_writeable_tlv_based!(ChannelConfig, {
442461
// LegacyChannelConfig. To make sure that serialization is not compatible with this one, we use
443462
// the next required type of 10, which if seen by the old serialization will always fail.
444463
(10, force_close_avoidance_max_fee_satoshis, required),
464+
(12, max_dust_htlc_exposure_multiplier_thousandths, required)
445465
});
446466

447467
/// A parallel struct to [`ChannelConfig`] to define partial updates.
@@ -452,6 +472,7 @@ pub struct ChannelConfigUpdate {
452472
pub cltv_expiry_delta: Option<u16>,
453473
pub max_dust_htlc_exposure_msat: Option<u64>,
454474
pub force_close_avoidance_max_fee_satoshis: Option<u64>,
475+
pub max_dust_htlc_exposure_multiplier_thousandths: Option<Option<u64>>,
455476
}
456477

457478
impl Default for ChannelConfigUpdate {
@@ -462,6 +483,7 @@ impl Default for ChannelConfigUpdate {
462483
cltv_expiry_delta: None,
463484
max_dust_htlc_exposure_msat: None,
464485
force_close_avoidance_max_fee_satoshis: None,
486+
max_dust_htlc_exposure_multiplier_thousandths: None,
465487
}
466488
}
467489
}
@@ -474,6 +496,7 @@ impl From<ChannelConfig> for ChannelConfigUpdate {
474496
cltv_expiry_delta: Some(config.cltv_expiry_delta),
475497
max_dust_htlc_exposure_msat: Some(config.max_dust_htlc_exposure_msat),
476498
force_close_avoidance_max_fee_satoshis: Some(config.force_close_avoidance_max_fee_satoshis),
499+
max_dust_htlc_exposure_multiplier_thousandths: Some(config.max_dust_htlc_exposure_multiplier_thousandths),
477500
}
478501
}
479502
}
@@ -513,6 +536,7 @@ impl crate::util::ser::Writeable for LegacyChannelConfig {
513536
(4, self.announced_channel, required),
514537
(6, self.commit_upfront_shutdown_pubkey, required),
515538
(8, self.options.forwarding_fee_base_msat, required),
539+
(10, self.options.max_dust_htlc_exposure_multiplier_thousandths, option),
516540
});
517541
Ok(())
518542
}
@@ -527,6 +551,7 @@ impl crate::util::ser::Readable for LegacyChannelConfig {
527551
let mut announced_channel = false;
528552
let mut commit_upfront_shutdown_pubkey = false;
529553
let mut forwarding_fee_base_msat = 0;
554+
let mut max_dust_htlc_exposure_multiplier_thousandths = None;
530555
read_tlv_fields!(reader, {
531556
(0, forwarding_fee_proportional_millionths, required),
532557
(1, max_dust_htlc_exposure_msat, (default_value, 5_000_000u64)),
@@ -535,6 +560,7 @@ impl crate::util::ser::Readable for LegacyChannelConfig {
535560
(4, announced_channel, required),
536561
(6, commit_upfront_shutdown_pubkey, required),
537562
(8, forwarding_fee_base_msat, required),
563+
(10, max_dust_htlc_exposure_multiplier_thousandths, option),
538564
});
539565
Ok(Self {
540566
options: ChannelConfig {
@@ -543,6 +569,7 @@ impl crate::util::ser::Readable for LegacyChannelConfig {
543569
cltv_expiry_delta,
544570
force_close_avoidance_max_fee_satoshis,
545571
forwarding_fee_base_msat,
572+
max_dust_htlc_exposure_multiplier_thousandths,
546573
},
547574
announced_channel,
548575
commit_upfront_shutdown_pubkey,

0 commit comments

Comments
 (0)