Update default dust exposure limit and the documentation thereof
authorMatt Corallo <git@bluematt.me>
Sun, 5 May 2024 00:44:07 +0000 (00:44 +0000)
committerMatt Corallo <git@bluematt.me>
Tue, 7 May 2024 14:13:55 +0000 (14:13 +0000)
Now that we're including excess counterparty commitment transaction
fees in our dust calculation, we need to update the docs
accordingly. We do so here, describing some of the considerations
and risks that come with the new changes.

We also take this opportunity to double the default value, as users
have regularly complained that non-anchor channels fail to send
HTLCs with the default settings with some feerates.

Fixes #2922

lightning/src/util/config.rs

index 2c8f03b93c89528798249868d98178cf0e23c052..2473eea26274500800a4e5ea11c9ce9e6530fde4 100644 (file)
@@ -360,7 +360,7 @@ impl Readable for ChannelHandshakeLimits {
        }
 }
 
-/// Options for how to set the max dust HTLC exposure allowed on a channel. See
+/// Options for how to set the max dust exposure allowed on a channel. See
 /// [`ChannelConfig::max_dust_htlc_exposure`] for details.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum MaxDustHTLCExposure {
@@ -374,19 +374,17 @@ pub enum MaxDustHTLCExposure {
        /// to this maximum the channel may be unable to send/receive HTLCs between the maximum dust
        /// exposure and the new minimum value for HTLCs to be economically viable to claim.
        FixedLimitMsat(u64),
-       /// This sets a multiplier on the estimated high priority feerate (sats/KW, as obtained from
-       /// [`FeeEstimator`]) to determine the maximum allowed dust exposure. If this variant is used
-       /// then the maximum dust exposure in millisatoshis is calculated as:
-       /// `high_priority_feerate_per_kw * value`. For example, with our default value
-       /// `FeeRateMultiplier(5000)`:
+       /// This sets a multiplier on the [`ConfirmationTarget::OnChainSweep`] feerate (in sats/KW) to
+       /// determine the maximum allowed dust exposure. If this variant is used then the maximum dust
+       /// exposure in millisatoshis is calculated as:
+       /// `feerate_per_kw * value`. For example, with our default value
+       /// `FeeRateMultiplier(10_000)`:
        ///
        /// - For the minimum fee rate of 1 sat/vByte (250 sat/KW, although the minimum
        /// defaults to 253 sats/KW for rounding, see [`FeeEstimator`]), the max dust exposure would
-       /// be 253 * 5000 = 1,265,000 msats.
+       /// be 253 * 10_000 = 2,530,000 msats.
        /// - For a fee rate of 30 sat/vByte (7500 sat/KW), the max dust exposure would be
-       /// 7500 * 5000 = 37,500,000 msats.
-       ///
-       /// This allows the maximum dust exposure to automatically scale with fee rate changes.
+       /// 7500 * 50_000 = 75,000,000 msats (0.00075 BTC).
        ///
        /// Note, if you're using a third-party fee estimator, this may leave you more exposed to a
        /// fee griefing attack, where your fee estimator may purposely overestimate the fee rate,
@@ -401,6 +399,7 @@ pub enum MaxDustHTLCExposure {
        /// by default this will be set to a [`Self::FixedLimitMsat`] of 5,000,000 msat.
        ///
        /// [`FeeEstimator`]: crate::chain::chaininterface::FeeEstimator
+       /// [`ConfirmationTarget::OnChainSweep`]: crate::chain::chaininterface::ConfirmationTarget::OnChainSweep
        FeeRateMultiplier(u64),
 }
 
@@ -453,13 +452,16 @@ pub struct ChannelConfig {
        ///
        /// [`MIN_CLTV_EXPIRY_DELTA`]: crate::ln::channelmanager::MIN_CLTV_EXPIRY_DELTA
        pub cltv_expiry_delta: u16,
-       /// Limit our total exposure to in-flight HTLCs which are burned to fees as they are too
-       /// small to claim on-chain.
+       /// Limit our total exposure to potential loss to on-chain fees on close, including in-flight
+       /// HTLCs which are burned to fees as they are too small to claim on-chain and fees on
+       /// commitment transaction(s) broadcasted by our counterparty in excess of our own fee estimate.
+       ///
+       /// # HTLC-based Dust Exposure
        ///
        /// When an HTLC present in one of our channels is below a "dust" threshold, the HTLC will
        /// not be claimable on-chain, instead being turned into additional miner fees if either
        /// party force-closes the channel. Because the threshold is per-HTLC, our total exposure
-       /// to such payments may be sustantial if there are many dust HTLCs present when the
+       /// to such payments may be substantial if there are many dust HTLCs present when the
        /// channel is force-closed.
        ///
        /// The dust threshold for each HTLC is based on the `dust_limit_satoshis` for each party in a
@@ -473,7 +475,42 @@ pub struct ChannelConfig {
        /// The selected limit is applied for sent, forwarded, and received HTLCs and limits the total
        /// exposure across all three types per-channel.
        ///
-       /// Default value: [`MaxDustHTLCExposure::FeeRateMultiplier`] with a multiplier of 5000.
+       /// # Transaction Fee Dust Exposure
+       ///
+       /// Further, counterparties broadcasting a commitment transaction in a force-close may result
+       /// in other balance being burned to fees, and thus all fees on commitment and HTLC
+       /// transactions in excess of our local fee estimates are included in the dust calculation.
+       ///
+       /// Because of this, another way to look at this limit is to divide it by 43,000 (or 218,750
+       /// for non-anchor channels) and see it as the maximum feerate disagreement (in sats/vB) per
+       /// non-dust HTLC we're allowed to have with our peers before risking a force-closure for
+       /// inbound channels.
+       // This works because, for anchor channels the on-chain cost is 172 weight (172+703 for
+       // non-anchors with an HTLC-Success transaction), i.e.
+       // dust_exposure_limit_msat / 1000 = 172 * feerate_in_sat_per_vb / 4 * HTLC count
+       // dust_exposure_limit_msat = 43,000 * feerate_in_sat_per_vb * HTLC count
+       // dust_exposure_limit_msat / HTLC count / 43,000 = feerate_in_sat_per_vb
+       ///
+       /// Thus, for the default value of 10_000 * a current feerate estimate of 10 sat/vB (or 2,500
+       /// sat/KW), we risk force-closure if we disagree with our peer by:
+       /// * `10_000 * 2_500 / 43_000 / (483*2)` = 0.6 sat/vB for anchor channels with 483 HTLCs in
+       ///   both directions (the maximum),
+       /// * `10_000 * 2_500 / 43_000 / (50*2)` = 5.8 sat/vB for anchor channels with 50 HTLCs in both
+       ///   directions (the LDK default max from [`ChannelHandshakeConfig::our_max_accepted_htlcs`])
+       /// * `10_000 * 2_500 / 218_750 / (483*2)` = 0.1 sat/vB for non-anchor channels with 483 HTLCs
+       ///   in both directions (the maximum),
+       /// * `10_000 * 2_500 / 218_750 / (50*2)` = 1.1 sat/vB for non-anchor channels with 50 HTLCs
+       ///   in both (the LDK default maximum from [`ChannelHandshakeConfig::our_max_accepted_htlcs`])
+       ///
+       /// Note that when using [`MaxDustHTLCExposure::FeeRateMultiplier`] this maximum disagreement
+       /// will scale linearly with increases (or decreases) in the our feerate estimates. Further,
+       /// for anchor channels we expect our counterparty to use a relatively low feerate estimate
+       /// while we use [`ConfirmationTarget::OnChainSweep`] (which should be relatively high) and
+       /// feerate disagreement force-closures should only occur when theirs is higher than ours.
+       ///
+       /// Default value: [`MaxDustHTLCExposure::FeeRateMultiplier`] with a multiplier of 10_000.
+       ///
+       /// [`ConfirmationTarget::OnChainSweep`]: crate::chain::chaininterface::ConfirmationTarget::OnChainSweep
        pub max_dust_htlc_exposure: MaxDustHTLCExposure,
        /// The additional fee we're willing to pay to avoid waiting for the counterparty's
        /// `to_self_delay` to reclaim funds.
@@ -561,7 +598,7 @@ impl Default for ChannelConfig {
                        forwarding_fee_proportional_millionths: 0,
                        forwarding_fee_base_msat: 1000,
                        cltv_expiry_delta: 6 * 12, // 6 blocks/hour * 12 hours
-                       max_dust_htlc_exposure: MaxDustHTLCExposure::FeeRateMultiplier(5000),
+                       max_dust_htlc_exposure: MaxDustHTLCExposure::FeeRateMultiplier(10000),
                        force_close_avoidance_max_fee_satoshis: 1000,
                        accept_underpaying_htlcs: false,
                }