You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Include excess commitment transaction fees in dust exposure
Transaction fees on counterparty commitment transactions are
ultimately not our money and thus are really "dust" from our PoV -
they're funds that may be ours during off-chain updates but are not
ours once we go on-chain.
Thus, here, we count any such fees in excess of our own fee
estimates towards dust exposure. We don't bother to make an
inbound/outbound channel distinction here as in most cases users
will use `MaxDustExposure::FeeRateMultiplier` which will scale
with the fee we set on outbound channels anyway.
Note that this also enables the dust exposure checks on anchor
channels during feerate updates. We'd previously elided these as
increases in the channel feerates do not change the HTLC dust
exposure, but now do for the fee dust exposure.
if htlc_stats.on_counterparty_tx_dust_exposure_msat as i64 + htlc_success_dust_limit as i64 * 1000 - 1 > max_dust_htlc_exposure_msat.try_into().unwrap_or(i64::max_value()) {
3054
+
3055
+
let excess_feerate_opt = self.feerate_per_kw.checked_sub(dust_exposure_limiting_feerate);
3056
+
if let Some(excess_feerate) = excess_feerate_opt {
) -> Result<(), ChannelError> where F::Target: FeeEstimator {
4120
4182
if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
4121
4183
return Err(ChannelError::Close("Got add HTLC message when channel was not in an operational state".to_owned()));
4122
4184
}
@@ -4137,7 +4199,8 @@ impl<SP: Deref> Channel<SP> where
4137
4199
return Err(ChannelError::Close(format!("Remote side tried to send less than our minimum HTLC value. Lower limit: ({}). Actual: ({})", self.context.holder_htlc_minimum_msat, msg.amount_msat)));
4138
4200
}
4139
4201
4140
-
let htlc_stats = self.context.get_pending_htlc_stats(None);
4202
+
let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
4203
+
let htlc_stats = self.context.get_pending_htlc_stats(None, dust_exposure_limiting_feerate);
4141
4204
if htlc_stats.pending_inbound_htlcs + 1 > self.context.holder_max_accepted_htlcs as usize {
4142
4205
return Err(ChannelError::Close(format!("Remote tried to push more than our max accepted HTLCs ({})", self.context.holder_max_accepted_htlcs)));
4143
4206
}
@@ -4989,7 +5052,8 @@ impl<SP: Deref> Channel<SP> where
4989
5052
}
4990
5053
4991
5054
// Before proposing a feerate update, check that we can actually afford the new fee.
4992
-
let htlc_stats = self.context.get_pending_htlc_stats(Some(feerate_per_kw));
5055
+
let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
5056
+
let htlc_stats = self.context.get_pending_htlc_stats(Some(feerate_per_kw), dust_exposure_limiting_feerate);
4993
5057
let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number);
4994
5058
let commitment_stats = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, true, logger);
4995
5059
let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, commitment_stats.num_nondust_htlcs + htlc_stats.on_holder_tx_outbound_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.context.get_channel_type()) * 1000;
@@ -5001,7 +5065,7 @@ impl<SP: Deref> Channel<SP> where
5001
5065
}
5002
5066
5003
5067
// Note, we evaluate pending htlc "preemptive" trimmed-to-dust threshold at the proposed `feerate_per_kw`.
5004
-
let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator);
5068
+
let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate);
5005
5069
if htlc_stats.on_holder_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
5006
5070
log_debug!(logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", feerate_per_kw);
5007
5071
return None;
@@ -5239,17 +5303,16 @@ impl<SP: Deref> Channel<SP> where
// Check that we won't be pushed over our dust exposure limit by the feerate increase.
5242
-
if !self.context.channel_type.supports_anchors_zero_fee_htlc_tx() {
5243
-
let htlc_stats = self.context.get_pending_htlc_stats(None);
5244
-
let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator);
5245
-
if htlc_stats.on_holder_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
5246
-
return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our own transactions (totaling {} msat)",
if htlc_stats.on_counterparty_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
5250
-
return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our counterparty's transactions (totaling {} msat)",
let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
5307
+
let htlc_stats = self.context.get_pending_htlc_stats(None, dust_exposure_limiting_feerate);
5308
+
let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate);
5309
+
if htlc_stats.on_holder_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
5310
+
return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our own transactions (totaling {} msat)",
if htlc_stats.on_counterparty_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
5314
+
return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our counterparty's transactions (totaling {} msat)",
0 commit comments