Skip to content

Drop non-anchor channel fee upper bound limit entirely #2696

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion fuzz/src/chanmon_consistency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ impl FeeEstimator for FuzzEstimator {
// always return a HighPriority feerate here which is >= the maximum Normal feerate and a
// Background feerate which is <= the minimum Normal feerate.
match conf_target {
ConfirmationTarget::MaxAllowedNonAnchorChannelRemoteFee => MAX_FEE * 10,
ConfirmationTarget::OnChainSweep => MAX_FEE,
ConfirmationTarget::ChannelCloseMinimum|ConfirmationTarget::AnchorChannelFee|ConfirmationTarget::MinAllowedAnchorChannelRemoteFee|ConfirmationTarget::MinAllowedNonAnchorChannelRemoteFee => 253,
ConfirmationTarget::NonAnchorChannelFee => cmp::min(self.ret_val.load(atomic::Ordering::Acquire), MAX_FEE),
Expand Down
4 changes: 2 additions & 2 deletions fuzz/src/full_stack.rs

Large diffs are not rendered by default.

17 changes: 0 additions & 17 deletions lightning/src/chain/chaininterface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,23 +53,6 @@ pub enum ConfirmationTarget {
/// to low hundreds of blocks to get our transaction on-chain, but we shouldn't risk too low a
/// fee - this should be a relatively high priority feerate.
OnChainSweep,
/// The highest feerate we will allow our channel counterparty to have in a non-anchor channel.
///
/// This is the feerate on the transaction which we (or our counterparty) will broadcast in
/// order to close the channel unilaterally. Because our counterparty must ensure they can
/// always broadcast the latest state, this value being too low will cause immediate
/// force-closures.
///
/// Allowing this value to be too high can allow our counterparty to burn our HTLC outputs to
/// dust, which can result in HTLCs failing or force-closures (when the dust HTLCs exceed
/// [`ChannelConfig::max_dust_htlc_exposure`]).
///
/// Because most nodes use a feerate estimate which is based on a relatively high priority
/// transaction entering the current mempool, setting this to a small multiple of your current
/// high priority feerate estimate should suffice.
///
/// [`ChannelConfig::max_dust_htlc_exposure`]: crate::util::config::ChannelConfig::max_dust_htlc_exposure
MaxAllowedNonAnchorChannelRemoteFee,
/// This is the lowest feerate we will allow our channel counterparty to have in an anchor
/// channel in order to close the channel if a channel party goes away.
///
Expand Down
34 changes: 3 additions & 31 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2162,20 +2162,6 @@ impl<SP: Deref> Channel<SP> where
feerate_per_kw: u32, cur_feerate_per_kw: Option<u32>, logger: &L
) -> Result<(), ChannelError> where F::Target: FeeEstimator, L::Target: Logger,
{
// We only bound the fee updates on the upper side to prevent completely absurd feerates,
// always accepting up to 25 sat/vByte or 10x our fee estimator's "High Priority" fee.
// We generally don't care too much if they set the feerate to something very high, but it
// could result in the channel being useless due to everything being dust. This doesn't
// apply to channels supporting anchor outputs since HTLC transactions are pre-signed with a
// zero fee, so their fee is no longer considered to determine dust limits.
if !channel_type.supports_anchors_zero_fee_htlc_tx() {
let upper_limit =
fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::MaxAllowedNonAnchorChannelRemoteFee) as u64;
if feerate_per_kw as u64 > upper_limit {
return Err(ChannelError::Close(format!("Peer's feerate much too high. Actual: {}. Our expected upper limit: {}", feerate_per_kw, upper_limit)));
}
}

let lower_limit_conf_target = if channel_type.supports_anchors_zero_fee_htlc_tx() {
ConfirmationTarget::MinAllowedAnchorChannelRemoteFee
} else {
Expand Down Expand Up @@ -3872,14 +3858,11 @@ impl<SP: Deref> Channel<SP> where
return Err(ChannelError::Close("Peer sent update_fee when we needed a channel_reestablish".to_owned()));
}
Channel::<SP>::check_remote_fee(&self.context.channel_type, fee_estimator, msg.feerate_per_kw, Some(self.context.feerate_per_kw), logger)?;
let feerate_over_dust_buffer = msg.feerate_per_kw > self.context.get_dust_buffer_feerate(None);

self.context.pending_update_fee = Some((msg.feerate_per_kw, FeeUpdateState::RemoteAnnounced));
self.context.update_time_counter += 1;
// If the feerate has increased over the previous dust buffer (note that
// `get_dust_buffer_feerate` considers the `pending_update_fee` status), check that we
// won't be pushed over our dust exposure limit by the feerate increase.
if feerate_over_dust_buffer {
// Check that we won't be pushed over our dust exposure limit by the feerate increase.
if !self.context.channel_type.supports_anchors_zero_fee_htlc_tx() {
let inbound_stats = self.context.get_inbound_pending_htlc_stats(None);
let outbound_stats = self.context.get_outbound_pending_htlc_stats(None);
let holder_tx_dust_exposure = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat;
Expand Down Expand Up @@ -7684,7 +7667,7 @@ mod tests {
use crate::ln::PaymentHash;
use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
use crate::ln::channel::InitFeatures;
use crate::ln::channel::{Channel, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, commit_tx_fee_msat};
use crate::ln::channel::{ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, commit_tx_fee_msat};
use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
use crate::ln::features::ChannelTypeFeatures;
use crate::ln::msgs::{ChannelUpdate, DecodeError, UnsignedChannelUpdate, MAX_VALUE_MSAT};
Expand Down Expand Up @@ -7726,17 +7709,6 @@ mod tests {
"MAX_FUNDING_SATOSHIS_NO_WUMBO is greater than all satoshis in existence");
}

#[test]
fn test_no_fee_check_overflow() {
// Previously, calling `check_remote_fee` with a fee of 0xffffffff would overflow in
// arithmetic, causing a panic with debug assertions enabled.
let fee_est = TestFeeEstimator { fee_est: 42 };
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_est);
assert!(Channel::<&TestKeysInterface>::check_remote_fee(
&ChannelTypeFeatures::only_static_remote_key(), &bounded_fee_estimator,
u32::max_value(), None, &&test_utils::TestLogger::new()).is_err());
}

struct Keys {
signer: InMemorySigner,
}
Expand Down
9 changes: 2 additions & 7 deletions lightning/src/util/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,8 @@ pub struct TestFeeEstimator {
pub sat_per_kw: Mutex<u32>,
}
impl chaininterface::FeeEstimator for TestFeeEstimator {
fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32 {
match confirmation_target {
ConfirmationTarget::MaxAllowedNonAnchorChannelRemoteFee => {
core::cmp::max(25 * 250, *self.sat_per_kw.lock().unwrap() * 10)
}
_ => *self.sat_per_kw.lock().unwrap(),
}
fn get_est_sat_per_1000_weight(&self, _confirmation_target: ConfirmationTarget) -> u32 {
*self.sat_per_kw.lock().unwrap()
}
}

Expand Down