@@ -4411,84 +4411,70 @@ where
4411
4411
4412
4412
#[rustfmt::skip]
4413
4413
fn can_accept_incoming_htlc<L: Deref>(
4414
- &self, funding: &FundingScope, msg: &msgs::UpdateAddHTLC,
4414
+ &self, funding: &FundingScope,
4415
4415
dust_exposure_limiting_feerate: Option<u32>, logger: &L,
4416
4416
) -> Result<(), LocalHTLCFailureReason>
4417
4417
where
4418
4418
L::Target: Logger,
4419
4419
{
4420
- let htlc_stats = self.get_pending_htlc_stats(funding, None, dust_exposure_limiting_feerate);
4420
+ // `Some(())` is for the fee spike buffer we keep for the remote if the channel is not zero fee. This deviates from the spec because the fee spike buffer requirement
4421
+ // doesn't exist on the receiver's side, only on the sender's. Note that with anchor
4422
+ // outputs we are no longer as sensitive to fee spikes, so we need to account for them.
4423
+ //
4424
+ // A `None` `HTLCCandidate` is used as in this case because we're already accounting for
4425
+ // the incoming HTLC as it has been fully committed by both sides.
4426
+ let fee_spike_buffer_htlc = if funding.get_channel_type().supports_anchor_zero_fee_commitments() {
4427
+ 0
4428
+ } else {
4429
+ 1
4430
+ };
4431
+ let next_commitment_htlcs = self.next_commitment_htlcs(None);
4432
+ let value_to_self_msat = self.get_next_commitment_value_to_self_msat(funding);
4433
+ let next_commitment_stats = SpecTxBuilder {}.get_builder_stats(funding.is_outbound(), funding.get_value_satoshis(), value_to_self_msat, &next_commitment_htlcs, fee_spike_buffer_htlc, self.feerate_per_kw, dust_exposure_limiting_feerate, funding.get_channel_type(), self.holder_dust_limit_satoshis, self.counterparty_dust_limit_satoshis);
4434
+
4421
4435
let max_dust_htlc_exposure_msat = self.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate);
4422
- let on_counterparty_tx_dust_htlc_exposure_msat = htlc_stats.on_counterparty_tx_dust_exposure_msat;
4423
- if on_counterparty_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
4436
+ if next_commitment_stats.on_counterparty_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
4424
4437
// Note that the total dust exposure includes both the dust HTLCs and the excess mining fees of the counterparty commitment transaction
4425
4438
log_info!(logger, "Cannot accept value that would put our total dust exposure at {} over the limit {} on counterparty commitment tx",
4426
- on_counterparty_tx_dust_htlc_exposure_msat , max_dust_htlc_exposure_msat);
4439
+ next_commitment_stats.on_counterparty_tx_dust_exposure_msat , max_dust_htlc_exposure_msat);
4427
4440
return Err(LocalHTLCFailureReason::DustLimitCounterparty)
4428
4441
}
4429
- let dust_buffer_feerate = self.get_dust_buffer_feerate(None);
4430
- let (htlc_success_tx_fee_sat, _) = second_stage_tx_fees_sat(
4431
- &funding.get_channel_type(), dust_buffer_feerate,
4432
- );
4433
- let exposure_dust_limit_success_sats = htlc_success_tx_fee_sat + self.holder_dust_limit_satoshis;
4434
- if msg.amount_msat / 1000 < exposure_dust_limit_success_sats {
4435
- let on_holder_tx_dust_htlc_exposure_msat = htlc_stats.on_holder_tx_dust_exposure_msat;
4436
- if on_holder_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
4437
- log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx",
4438
- on_holder_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
4439
- return Err(LocalHTLCFailureReason::DustLimitHolder)
4440
- }
4442
+ if next_commitment_stats.on_holder_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
4443
+ // Note: We now always check holder dust exposure, whereas we previously would only
4444
+ // do it if the incoming HTLC was dust on our own commitment transaction
4445
+ log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx",
4446
+ next_commitment_stats.on_holder_tx_dust_exposure_msat, max_dust_htlc_exposure_msat);
4447
+ return Err(LocalHTLCFailureReason::DustLimitHolder)
4441
4448
}
4442
4449
4443
4450
if !funding.is_outbound() {
4444
- let removed_outbound_total_msat: u64 = self.pending_outbound_htlcs
4445
- .iter()
4446
- .filter_map(|htlc| {
4447
- matches!(
4448
- htlc.state,
4449
- OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_, _))
4450
- | OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_, _))
4451
- )
4452
- .then_some(htlc.amount_msat)
4453
- })
4454
- .sum();
4455
- let pending_value_to_self_msat =
4456
- funding.value_to_self_msat + htlc_stats.pending_inbound_htlcs_value_msat - removed_outbound_total_msat;
4457
- let pending_remote_value_msat =
4458
- funding.get_value_satoshis() * 1000 - pending_value_to_self_msat;
4459
- // Subtract any non-HTLC outputs from the local and remote balances
4460
- let (_, remote_balance_before_fee_msat) = SpecTxBuilder {}.subtract_non_htlc_outputs(
4461
- funding.is_outbound(),
4462
- pending_value_to_self_msat,
4463
- pending_remote_value_msat,
4464
- funding.get_channel_type()
4465
- );
4466
-
4467
- // `Some(())` is for the fee spike buffer we keep for the remote if the channel is
4468
- // not zero fee. This deviates from the spec because the fee spike buffer requirement
4469
- // doesn't exist on the receiver's side, only on the sender's. Note that with anchor
4470
- // outputs we are no longer as sensitive to fee spikes, so we need to account for them.
4471
- //
4472
- // A `None` `HTLCCandidate` is used as in this case because we're already accounting for
4473
- // the incoming HTLC as it has been fully committed by both sides.
4474
- let fee_spike_buffer_htlc = if funding.get_channel_type().supports_anchor_zero_fee_commitments() {
4475
- None
4476
- } else {
4477
- Some(())
4478
- };
4479
-
4480
- let mut remote_fee_cost_incl_stuck_buffer_msat = self.next_remote_commit_tx_fee_msat(
4481
- funding, None, fee_spike_buffer_htlc,
4482
- );
4451
+ let mut remote_fee_cost_incl_stuck_buffer_msat = next_commitment_stats.counterparty_commit_tx_fee_sat * 1000;
4483
4452
if !funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
4484
4453
remote_fee_cost_incl_stuck_buffer_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
4485
4454
}
4455
+ let remote_balance_before_fee_msat = next_commitment_stats.counterparty_balance_msat.unwrap_or(0);
4486
4456
if remote_balance_before_fee_msat.saturating_sub(funding.holder_selected_channel_reserve_satoshis * 1000) < remote_fee_cost_incl_stuck_buffer_msat {
4487
4457
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", &self.channel_id());
4488
4458
return Err(LocalHTLCFailureReason::FeeSpikeBuffer);
4489
4459
}
4490
4460
}
4491
4461
4462
+ #[cfg(any(test, fuzzing))]
4463
+ {
4464
+ let next_commitment_stats = if fee_spike_buffer_htlc == 1 {
4465
+ SpecTxBuilder {}.get_builder_stats(funding.is_outbound(), funding.get_value_satoshis(), value_to_self_msat, &next_commitment_htlcs, 0, self.feerate_per_kw, dust_exposure_limiting_feerate, funding.get_channel_type(), self.holder_dust_limit_satoshis, self.counterparty_dust_limit_satoshis)
4466
+ } else {
4467
+ next_commitment_stats
4468
+ };
4469
+ let mut predicted_htlcs = next_commitment_htlcs;
4470
+ predicted_htlcs.sort_unstable();
4471
+ *funding.next_remote_fee.lock().unwrap() = PredictedNextFee {
4472
+ predicted_feerate: self.feerate_per_kw,
4473
+ predicted_htlcs,
4474
+ predicted_fee_sat: next_commitment_stats.counterparty_commit_tx_fee_sat,
4475
+ };
4476
+ }
4477
+
4492
4478
Ok(())
4493
4479
}
4494
4480
@@ -9451,7 +9437,7 @@ where
9451
9437
/// this function determines whether to fail the HTLC, or forward / claim it.
9452
9438
#[rustfmt::skip]
9453
9439
pub fn can_accept_incoming_htlc<F: Deref, L: Deref>(
9454
- &self, msg: &msgs::UpdateAddHTLC, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: L
9440
+ &self, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: L
9455
9441
) -> Result<(), LocalHTLCFailureReason>
9456
9442
where
9457
9443
F::Target: FeeEstimator,
@@ -9467,7 +9453,7 @@ where
9467
9453
9468
9454
core::iter::once(&self.funding)
9469
9455
.chain(self.pending_funding.iter())
9470
- .try_for_each(|funding| self.context.can_accept_incoming_htlc(funding, msg, dust_exposure_limiting_feerate, &logger))
9456
+ .try_for_each(|funding| self.context.can_accept_incoming_htlc(funding, dust_exposure_limiting_feerate, &logger))
9471
9457
}
9472
9458
9473
9459
pub fn get_cur_holder_commitment_transaction_number(&self) -> u64 {
0 commit comments