Skip to content

Commit 101aa6f

Browse files
authored
Merge pull request #3796 from tankyleo/2025-05-dont-dip-into-reserve
Do not dip into the funder's reserve to cover the two anchors
2 parents 1156efb + 0cd16eb commit 101aa6f

File tree

2 files changed

+43
-20
lines changed

2 files changed

+43
-20
lines changed

lightning/src/ln/channel.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3808,7 +3808,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
38083808
if update_fee {
38093809
debug_assert!(!funding.is_outbound());
38103810
let counterparty_reserve_we_require_msat = funding.holder_selected_channel_reserve_satoshis * 1000;
3811-
if commitment_data.stats.remote_balance_before_fee_anchors_msat < commitment_data.stats.total_fee_sat * 1000 + counterparty_reserve_we_require_msat {
3811+
if commitment_data.stats.remote_balance_before_fee_anchors_msat < commitment_data.stats.total_fee_sat * 1000 + commitment_data.stats.total_anchors_sat * 1000 + counterparty_reserve_we_require_msat {
38123812
return Err(ChannelError::close("Funding remote cannot afford proposed new fee".to_owned()));
38133813
}
38143814
}
@@ -6724,7 +6724,7 @@ impl<SP: Deref> FundedChannel<SP> where
67246724
);
67256725
let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, commitment_data.tx.nondust_htlcs().len() + htlc_stats.on_holder_tx_outbound_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.funding.get_channel_type()) * 1000;
67266726
let holder_balance_msat = commitment_data.stats.local_balance_before_fee_anchors_msat - htlc_stats.outbound_holding_cell_msat;
6727-
if holder_balance_msat < buffer_fee_msat + self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
6727+
if holder_balance_msat < buffer_fee_msat + commitment_data.stats.total_anchors_sat * 1000 + self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
67286728
//TODO: auto-close after a number of failures?
67296729
log_debug!(logger, "Cannot afford to send new feerate at {}", feerate_per_kw);
67306730
return None;

lightning/src/ln/update_fee_tests.rs

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use crate::ln::chan_utils::{
66
COMMITMENT_TX_WEIGHT_PER_HTLC,
77
};
88
use crate::ln::channel::{
9-
get_holder_selected_channel_reserve_satoshis, CONCURRENT_INBOUND_HTLC_FEE_BUFFER,
10-
MIN_AFFORDABLE_HTLC_COUNT,
9+
get_holder_selected_channel_reserve_satoshis, ANCHOR_OUTPUT_VALUE_SATOSHI,
10+
CONCURRENT_INBOUND_HTLC_FEE_BUFFER, MIN_AFFORDABLE_HTLC_COUNT,
1111
};
1212
use crate::ln::channelmanager::PaymentId;
1313
use crate::ln::functional_test_utils::*;
@@ -388,11 +388,22 @@ pub fn test_update_fee_vanilla() {
388388
check_added_monitors(&nodes[1], 1);
389389
}
390390

391-
#[xtest(feature = "_externalize_tests")]
392-
pub fn test_update_fee_that_funder_cannot_afford() {
391+
pub fn do_test_update_fee_that_funder_cannot_afford(channel_type_features: ChannelTypeFeatures) {
393392
let chanmon_cfgs = create_chanmon_cfgs(2);
394393
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
395-
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
394+
395+
let mut default_config = test_default_channel_config();
396+
if channel_type_features == ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() {
397+
default_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
398+
// this setting is also needed to create an anchor channel
399+
default_config.manually_accept_inbound_channels = true;
400+
}
401+
402+
let node_chanmgrs = create_node_chanmgrs(
403+
2,
404+
&node_cfgs,
405+
&[Some(default_config.clone()), Some(default_config.clone())],
406+
);
396407
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
397408

398409
let node_a_id = nodes[0].node.get_our_node_id();
@@ -409,22 +420,26 @@ pub fn test_update_fee_that_funder_cannot_afford() {
409420
);
410421
let channel_id = chan.2;
411422
let secp_ctx = Secp256k1::new();
412-
let default_config = UserConfig::default();
413423
let bs_channel_reserve_sats =
414424
get_holder_selected_channel_reserve_satoshis(channel_value, &default_config);
415-
416-
let channel_type_features = ChannelTypeFeatures::only_static_remote_key();
425+
let (anchor_outputs_value_sats, outputs_num_no_htlcs) =
426+
if channel_type_features.supports_anchors_zero_fee_htlc_tx() {
427+
(ANCHOR_OUTPUT_VALUE_SATOSHI * 2, 4)
428+
} else {
429+
(0, 2)
430+
};
417431

418432
// Calculate the maximum feerate that A can afford. Note that we don't send an update_fee
419433
// CONCURRENT_INBOUND_HTLC_FEE_BUFFER HTLCs before actually running out of local balance, so we
420434
// calculate two different feerates here - the expected local limit as well as the expected
421435
// remote limit.
422-
let feerate = ((channel_value - bs_channel_reserve_sats - push_sats) * 1000
423-
/ (commitment_tx_base_weight(&channel_type_features)
424-
+ CONCURRENT_INBOUND_HTLC_FEE_BUFFER as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC))
425-
as u32;
426-
let non_buffer_feerate = ((channel_value - bs_channel_reserve_sats - push_sats) * 1000
427-
/ commitment_tx_base_weight(&channel_type_features)) as u32;
436+
let feerate =
437+
((channel_value - bs_channel_reserve_sats - push_sats - anchor_outputs_value_sats) * 1000
438+
/ (commitment_tx_base_weight(&channel_type_features)
439+
+ CONCURRENT_INBOUND_HTLC_FEE_BUFFER as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC)) as u32;
440+
let non_buffer_feerate =
441+
((channel_value - bs_channel_reserve_sats - push_sats - anchor_outputs_value_sats) * 1000
442+
/ commitment_tx_base_weight(&channel_type_features)) as u32;
428443
{
429444
let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
430445
*feerate_lock = feerate;
@@ -441,8 +456,8 @@ pub fn test_update_fee_that_funder_cannot_afford() {
441456
{
442457
let commitment_tx = get_local_commitment_txn!(nodes[1], channel_id)[0].clone();
443458

444-
//We made sure neither party's funds are below the dust limit and there are no HTLCs here
445-
assert_eq!(commitment_tx.output.len(), 2);
459+
// We made sure neither party's funds are below the dust limit and there are no HTLCs here
460+
assert_eq!(commitment_tx.output.len(), outputs_num_no_htlcs);
446461
let total_fee: u64 = commit_tx_fee_msat(feerate, 0, &channel_type_features) / 1000;
447462
let mut actual_fee =
448463
commitment_tx.output.iter().fold(0, |acc, output| acc + output.value.to_sat());
@@ -486,8 +501,8 @@ pub fn test_update_fee_that_funder_cannot_afford() {
486501
&remote_point,
487502
push_sats,
488503
channel_value
489-
- push_sats - commit_tx_fee_msat(non_buffer_feerate + 4, 0, &channel_type_features)
490-
/ 1000,
504+
- push_sats - anchor_outputs_value_sats
505+
- commit_tx_fee_msat(non_buffer_feerate + 4, 0, &channel_type_features) / 1000,
491506
non_buffer_feerate + 4,
492507
nondust_htlcs,
493508
&local_chan.funding().channel_transaction_parameters.as_counterparty_broadcastable(),
@@ -526,6 +541,14 @@ pub fn test_update_fee_that_funder_cannot_afford() {
526541
check_closed_event!(nodes[1], 1, reason, [node_a_id], channel_value);
527542
}
528543

544+
#[xtest(feature = "_externalize_tests")]
545+
pub fn test_update_fee_that_funder_cannot_afford() {
546+
do_test_update_fee_that_funder_cannot_afford(ChannelTypeFeatures::only_static_remote_key());
547+
do_test_update_fee_that_funder_cannot_afford(
548+
ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(),
549+
);
550+
}
551+
529552
#[xtest(feature = "_externalize_tests")]
530553
pub fn test_update_fee_that_saturates_subs() {
531554
// Check that when a remote party sends us an `update_fee` message that results in a total fee

0 commit comments

Comments
 (0)