Skip to content

Commit 74dd5fc

Browse files
committed
can_accept_incoming_htlc
1 parent 72fd3f5 commit 74dd5fc

File tree

2 files changed

+45
-59
lines changed

2 files changed

+45
-59
lines changed

lightning/src/ln/channel.rs

Lines changed: 44 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -4411,84 +4411,70 @@ where
44114411

44124412
#[rustfmt::skip]
44134413
fn can_accept_incoming_htlc<L: Deref>(
4414-
&self, funding: &FundingScope, msg: &msgs::UpdateAddHTLC,
4414+
&self, funding: &FundingScope,
44154415
dust_exposure_limiting_feerate: Option<u32>, logger: &L,
44164416
) -> Result<(), LocalHTLCFailureReason>
44174417
where
44184418
L::Target: Logger,
44194419
{
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+
44214435
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 {
44244437
// Note that the total dust exposure includes both the dust HTLCs and the excess mining fees of the counterparty commitment transaction
44254438
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);
44274440
return Err(LocalHTLCFailureReason::DustLimitCounterparty)
44284441
}
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)
44414448
}
44424449

44434450
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;
44834452
if !funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
44844453
remote_fee_cost_incl_stuck_buffer_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
44854454
}
4455+
let remote_balance_before_fee_msat = next_commitment_stats.counterparty_balance_msat.unwrap_or(0);
44864456
if remote_balance_before_fee_msat.saturating_sub(funding.holder_selected_channel_reserve_satoshis * 1000) < remote_fee_cost_incl_stuck_buffer_msat {
44874457
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", &self.channel_id());
44884458
return Err(LocalHTLCFailureReason::FeeSpikeBuffer);
44894459
}
44904460
}
44914461

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+
44924478
Ok(())
44934479
}
44944480

@@ -9451,7 +9437,7 @@ where
94519437
/// this function determines whether to fail the HTLC, or forward / claim it.
94529438
#[rustfmt::skip]
94539439
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
94559441
) -> Result<(), LocalHTLCFailureReason>
94569442
where
94579443
F::Target: FeeEstimator,
@@ -9467,7 +9453,7 @@ where
94679453

94689454
core::iter::once(&self.funding)
94699455
.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))
94719457
}
94729458

94739459
pub fn get_cur_holder_commitment_transaction_number(&self) -> u64 {

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6262,7 +6262,7 @@ where
62626262
&chan.context,
62636263
Some(update_add_htlc.payment_hash),
62646264
);
6265-
chan.can_accept_incoming_htlc(update_add_htlc, &self.fee_estimator, &logger)
6265+
chan.can_accept_incoming_htlc(&self.fee_estimator, &logger)
62666266
},
62676267
) {
62686268
Some(Ok(_)) => {},

0 commit comments

Comments
 (0)