Skip to content

Commit 27fba2d

Browse files
committed
Only account for fee spike buffer multiple on non-anchor channels
Anchor outputs channels are no longer susceptible to fee spikes as they now mostly target the dynamic minimum mempool fee and can contribute the remainder of fees when closing.
1 parent 834f4d7 commit 27fba2d

File tree

2 files changed

+26
-14
lines changed

2 files changed

+26
-14
lines changed

fuzz/src/chanmon_consistency.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -1223,7 +1223,10 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
12231223
0x6d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1, &mut payment_id, &mut payment_idx); },
12241224

12251225
0x80 => {
1226-
let max_feerate = last_htlc_clear_fee_a * FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
1226+
let mut max_feerate = last_htlc_clear_fee_a;
1227+
if !anchors {
1228+
max_feerate *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
1229+
}
12271230
if fee_est_a.ret_val.fetch_add(250, atomic::Ordering::AcqRel) + 250 > max_feerate {
12281231
fee_est_a.ret_val.store(max_feerate, atomic::Ordering::Release);
12291232
}
@@ -1232,7 +1235,10 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
12321235
0x81 => { fee_est_a.ret_val.store(253, atomic::Ordering::Release); nodes[0].maybe_update_chan_fees(); },
12331236

12341237
0x84 => {
1235-
let max_feerate = last_htlc_clear_fee_b * FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
1238+
let mut max_feerate = last_htlc_clear_fee_b;
1239+
if !anchors {
1240+
max_feerate *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
1241+
}
12361242
if fee_est_b.ret_val.fetch_add(250, atomic::Ordering::AcqRel) + 250 > max_feerate {
12371243
fee_est_b.ret_val.store(max_feerate, atomic::Ordering::Release);
12381244
}
@@ -1241,7 +1247,10 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
12411247
0x85 => { fee_est_b.ret_val.store(253, atomic::Ordering::Release); nodes[1].maybe_update_chan_fees(); },
12421248

12431249
0x88 => {
1244-
let max_feerate = last_htlc_clear_fee_c * FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
1250+
let mut max_feerate = last_htlc_clear_fee_c;
1251+
if !anchors {
1252+
max_feerate *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
1253+
}
12451254
if fee_est_c.ret_val.fetch_add(250, atomic::Ordering::AcqRel) + 250 > max_feerate {
12461255
fee_est_c.ret_val.store(max_feerate, atomic::Ordering::Release);
12471256
}

lightning/src/ln/channel.rs

+14-11
Original file line numberDiff line numberDiff line change
@@ -1692,9 +1692,13 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
16921692
}
16931693

16941694
let htlc_above_dust = HTLCCandidate::new(real_dust_limit_timeout_sat * 1000, HTLCInitiator::LocalOffered);
1695-
let max_reserved_commit_tx_fee_msat = FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE * context.next_local_commit_tx_fee_msat(htlc_above_dust, Some(()));
1695+
let mut max_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(htlc_above_dust, Some(()));
16961696
let htlc_dust = HTLCCandidate::new(real_dust_limit_timeout_sat * 1000 - 1, HTLCInitiator::LocalOffered);
1697-
let min_reserved_commit_tx_fee_msat = FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE * context.next_local_commit_tx_fee_msat(htlc_dust, Some(()));
1697+
let mut min_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(htlc_dust, Some(()));
1698+
if !context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
1699+
max_reserved_commit_tx_fee_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
1700+
min_reserved_commit_tx_fee_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
1701+
}
16981702

16991703
// We will first subtract the fee as if we were above-dust. Then, if the resulting
17001704
// value ends up being below dust, we have this fee available again. In that case,
@@ -2856,16 +2860,15 @@ impl<SP: Deref> Channel<SP> where
28562860
0
28572861
};
28582862
if !self.context.is_outbound() {
2859-
// `2 *` and `Some(())` is for the fee spike buffer we keep for the remote. This deviates from
2860-
// the spec because in the spec, the fee spike buffer requirement doesn't exist on the
2861-
// receiver's side, only on the sender's.
2862-
// Note that when we eventually remove support for fee updates and switch to anchor output
2863-
// fees, we will drop the `2 *`, since we no longer be as sensitive to fee spikes. But, keep
2864-
// the extra htlc when calculating the next remote commitment transaction fee as we should
2865-
// still be able to afford adding this HTLC plus one more future HTLC, regardless of being
2866-
// sensitive to fee spikes.
2863+
// `Some(())` is for the fee spike buffer we keep for the remote. This deviates from
2864+
// the spec because the fee spike buffer requirement doesn't exist on the receiver's
2865+
// side, only on the sender's. Note that with anchor outputs we are no longer as
2866+
// sensitive to fee spikes, so we need to account for them.
28672867
let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered);
2868-
let remote_fee_cost_incl_stuck_buffer_msat = 2 * self.context.next_remote_commit_tx_fee_msat(htlc_candidate, Some(()));
2868+
let mut remote_fee_cost_incl_stuck_buffer_msat = self.context.next_remote_commit_tx_fee_msat(htlc_candidate, Some(()));
2869+
if !self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
2870+
remote_fee_cost_incl_stuck_buffer_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
2871+
}
28692872
if pending_remote_value_msat.saturating_sub(msg.amount_msat).saturating_sub(self.context.holder_selected_channel_reserve_satoshis * 1000).saturating_sub(anchor_outputs_value_msat) < remote_fee_cost_incl_stuck_buffer_msat {
28702873
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
28712874
// the HTLC, i.e. its status is already set to failing.

0 commit comments

Comments
 (0)