Skip to content

Commit 61d72f8

Browse files
committed
Add config flag for failing back HTLCs pending downstream confirmation
1 parent bbe20c3 commit 61d72f8

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

lightning/src/util/config.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,62 @@ pub struct ChannelConfig {
485485
/// [`PaymentClaimable::counterparty_skimmed_fee_msat`]: crate::events::Event::PaymentClaimable::counterparty_skimmed_fee_msat
486486
// TODO: link to bLIP when it's merged
487487
pub accept_underpaying_htlcs: bool,
488+
/// A multiplier on the on-chain fees (assuming the high priority feerate) setting the
489+
/// threshold for an HTLC's value for which we will fail the HTLC early to prevent closing a
490+
/// channel. This field is denoted in millionths.
491+
///
492+
/// If we have forwarded an HTLC to a peer and they have not claimed it on or off-chain by the
493+
/// time the previous hop's HTLC timeout expires, we can choose to fail back the HTLC to save
494+
/// the upstream channel from closing on-chain, or we can risk the channel in hopes of getting
495+
/// a last-minute preimage from downstream. The risk may or may not be worth it depending on
496+
/// how large the HTLC is relative to how much we will lose in fees if the channel closes.
497+
///
498+
/// This roughly translates to how much the HTLC value should be proportional to the amount
499+
/// we'll pay on chain. So if the value of this flag is 1,500,000, it means we should only risk
500+
/// going on-chain if the HTLC value is at least 1.5x the amount we'll pay on chain.
501+
///
502+
/// Based on this multiplier, we will fail back HTLCs in the described situation if the HTLC's
503+
/// value is below the following threshold:
504+
/// `high_priority_feerate_per_kw * total_weight * early_fail_multiplier / 1,000,000,000` (we
505+
/// divide by 1,000,000,000 because feerate is denoted by kiloweight units, and the multiplier
506+
/// is denoted in millionths).
507+
///
508+
/// Total weight is defined by the situation where we took the risk closing on-chain, and the
509+
/// result was in our favor, i.e. we claimed with an HTLC-success transaction. So, we use the
510+
/// sum of the weight of the commitment transaction (if we're the funder of the channel) and
511+
/// the weight of an HTLC-success transaction, including one extra P2WPKH input and output
512+
/// to account for fee-bumping. These weights are calculated as follows:
513+
///
514+
/// [Commitment transaction weight](https://github.com/lightning/bolts/blob/master/03-transactions.md#expected-weight-of-the-commitment-transaction):
515+
/// * (no option_anchors) 500 + 172 * num-htlc-outputs + 224 weight
516+
/// * (option_anchors) 900 + 172 * num-htlc-outputs + 224 weight
517+
///
518+
/// [HTLC-success weight](https://github.com/lightning/bolts/blob/master/03-transactions.md#expected-weight-of-htlc-timeout-and-htlc-success-transactions):
519+
/// * HTLC-success weight: 703 (706 with anchors) weight
520+
/// * 1 input + witness spending a P2WPKH output: 272 weight
521+
/// * 1 P2WPKH output: 31 bytes * 4 = 124 weight
522+
/// * Total: 1099 (1102 with anchors) weight
523+
///
524+
/// Sample calculations:
525+
/// * Total weight assuming we're the funder, on a non-anchor channel with 1 HTLC:
526+
/// 500 + 172 * 1 + 224 + 1099 = 1995.
527+
/// * Feerate: 1 sat/vbyte -> 253 sats/KW (250 sat/KW, although the minimum defaults to 253
528+
/// sats/KW for rounding, see [`FeeEstimator`])
529+
/// * Cost to claim-onchain: 1995 * 253 / 1000 = 504 sats.
530+
/// * Minimum HTLC value required to risk going on-chain:
531+
/// 1995 * 253 * 1,500,000 / 1,000 / 1,000,000 = 757 sats.
532+
/// * Feerate: 30 sat/vbyte -> 7,500 sat/KW
533+
/// * Cost to claim on-chain: 1995 * 7500 / 1000 = 14,962 sats.
534+
/// * Minimum HTLC value required to risk going on-chain:
535+
/// 1995 * 7500 * 1,500,000 / 1,000 / 1,000,000 = 22,443 sats.
536+
///
537+
/// If you prefer to always let upstream HTLCs resolve on-chain in the event that your
538+
/// downstream channel takes too long to confirm on-chain, just set this multiplier to 0.
539+
///
540+
/// Default value: 1,500,000.
541+
///
542+
/// [`FeeEstimator`]: crate::chain::chaininterface::FeeEstimator
543+
pub early_fail_multiplier: u64,
488544
}
489545

490546
impl ChannelConfig {
@@ -518,6 +574,7 @@ impl Default for ChannelConfig {
518574
max_dust_htlc_exposure: MaxDustHTLCExposure::FeeRateMultiplier(5000),
519575
force_close_avoidance_max_fee_satoshis: 1000,
520576
accept_underpaying_htlcs: false,
577+
early_fail_multiplier: 1_500_000,
521578
}
522579
}
523580
}
@@ -534,6 +591,7 @@ impl crate::util::ser::Writeable for ChannelConfig {
534591
(2, self.forwarding_fee_base_msat, required),
535592
(3, self.max_dust_htlc_exposure, required),
536593
(4, self.cltv_expiry_delta, required),
594+
(5, self.early_fail_multiplier, required),
537595
(6, max_dust_htlc_exposure_msat_fixed_limit, required),
538596
// ChannelConfig serialized this field with a required type of 8 prior to the introduction of
539597
// LegacyChannelConfig. To make sure that serialization is not compatible with this one, we use
@@ -553,12 +611,14 @@ impl crate::util::ser::Readable for ChannelConfig {
553611
let mut max_dust_htlc_exposure_msat = None;
554612
let mut max_dust_htlc_exposure_enum = None;
555613
let mut force_close_avoidance_max_fee_satoshis = 1000;
614+
let mut early_fail_multiplier = 1_500_000;
556615
read_tlv_fields!(reader, {
557616
(0, forwarding_fee_proportional_millionths, required),
558617
(1, accept_underpaying_htlcs, (default_value, false)),
559618
(2, forwarding_fee_base_msat, required),
560619
(3, max_dust_htlc_exposure_enum, option),
561620
(4, cltv_expiry_delta, required),
621+
(5, early_fail_multiplier, (default_value, 1_500_000u64)),
562622
// Has always been written, but became optionally read in 0.0.116
563623
(6, max_dust_htlc_exposure_msat, option),
564624
(10, force_close_avoidance_max_fee_satoshis, required),
@@ -573,6 +633,7 @@ impl crate::util::ser::Readable for ChannelConfig {
573633
cltv_expiry_delta,
574634
max_dust_htlc_exposure: max_dust_htlc_exposure_msat,
575635
force_close_avoidance_max_fee_satoshis,
636+
early_fail_multiplier,
576637
})
577638
}
578639
}
@@ -585,6 +646,7 @@ pub struct ChannelConfigUpdate {
585646
pub cltv_expiry_delta: Option<u16>,
586647
pub max_dust_htlc_exposure_msat: Option<MaxDustHTLCExposure>,
587648
pub force_close_avoidance_max_fee_satoshis: Option<u64>,
649+
pub early_fail_multiplier: Option<u64>,
588650
}
589651

590652
impl Default for ChannelConfigUpdate {
@@ -595,6 +657,7 @@ impl Default for ChannelConfigUpdate {
595657
cltv_expiry_delta: None,
596658
max_dust_htlc_exposure_msat: None,
597659
force_close_avoidance_max_fee_satoshis: None,
660+
early_fail_multiplier: None,
598661
}
599662
}
600663
}
@@ -607,6 +670,7 @@ impl From<ChannelConfig> for ChannelConfigUpdate {
607670
cltv_expiry_delta: Some(config.cltv_expiry_delta),
608671
max_dust_htlc_exposure_msat: Some(config.max_dust_htlc_exposure),
609672
force_close_avoidance_max_fee_satoshis: Some(config.force_close_avoidance_max_fee_satoshis),
673+
early_fail_multiplier: Some(config.early_fail_multiplier),
610674
}
611675
}
612676
}
@@ -650,6 +714,7 @@ impl crate::util::ser::Writeable for LegacyChannelConfig {
650714
(4, self.announced_channel, required),
651715
(5, self.options.max_dust_htlc_exposure, required),
652716
(6, self.commit_upfront_shutdown_pubkey, required),
717+
(7, self.options.early_fail_multiplier, required),
653718
(8, self.options.forwarding_fee_base_msat, required),
654719
});
655720
Ok(())
@@ -666,6 +731,7 @@ impl crate::util::ser::Readable for LegacyChannelConfig {
666731
let mut commit_upfront_shutdown_pubkey = false;
667732
let mut forwarding_fee_base_msat = 0;
668733
let mut max_dust_htlc_exposure_enum = None;
734+
let mut early_fail_multiplier = 1_500_000;
669735
read_tlv_fields!(reader, {
670736
(0, forwarding_fee_proportional_millionths, required),
671737
// Has always been written, but became optionally read in 0.0.116
@@ -674,6 +740,7 @@ impl crate::util::ser::Readable for LegacyChannelConfig {
674740
(3, force_close_avoidance_max_fee_satoshis, (default_value, 1000u64)),
675741
(4, announced_channel, required),
676742
(5, max_dust_htlc_exposure_enum, option),
743+
(7, early_fail_multiplier, (default_value, 1_500_000u64)),
677744
(6, commit_upfront_shutdown_pubkey, required),
678745
(8, forwarding_fee_base_msat, required),
679746
});
@@ -689,6 +756,7 @@ impl crate::util::ser::Readable for LegacyChannelConfig {
689756
force_close_avoidance_max_fee_satoshis,
690757
forwarding_fee_base_msat,
691758
accept_underpaying_htlcs: false,
759+
early_fail_multiplier,
692760
},
693761
announced_channel,
694762
commit_upfront_shutdown_pubkey,

0 commit comments

Comments
 (0)