@@ -41,10 +41,10 @@ use crate::ln::chan_utils;
41
41
#[cfg(splicing)]
42
42
use crate::ln::chan_utils::FUNDING_TRANSACTION_WITNESS_WEIGHT;
43
43
use crate::ln::chan_utils::{
44
- get_commitment_transaction_number_obscure_factor, htlc_success_tx_weight ,
45
- htlc_timeout_tx_weight, max_htlcs, ChannelPublicKeys, ChannelTransactionParameters ,
46
- ClosingTransaction, CommitmentTransaction, CounterpartyChannelTransactionParameters ,
47
- CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HolderCommitmentTransaction,
44
+ get_commitment_transaction_number_obscure_factor, max_htlcs, ChannelPublicKeys ,
45
+ ChannelTransactionParameters, ClosingTransaction, CommitmentTransaction ,
46
+ CounterpartyChannelTransactionParameters, CounterpartyCommitmentSecrets ,
47
+ HTLCOutputInCommitment, HolderCommitmentTransaction,
48
48
};
49
49
use crate::ln::channel_state::{
50
50
ChannelShutdownState, CounterpartyForwardingInfo, InboundHTLCDetails, InboundHTLCStateDetails,
@@ -284,27 +284,6 @@ struct InboundHTLCOutput {
284
284
state: InboundHTLCState,
285
285
}
286
286
287
- impl InboundHTLCOutput {
288
- fn is_dust(
289
- &self, local: bool, feerate_per_kw: u32, broadcaster_dust_limit_sat: u64,
290
- features: &ChannelTypeFeatures,
291
- ) -> bool {
292
- let htlc_tx_fee_sat = if features.supports_anchors_zero_fee_htlc_tx() {
293
- 0
294
- } else {
295
- let htlc_tx_weight = if !local {
296
- // this is an offered htlc
297
- htlc_timeout_tx_weight(features)
298
- } else {
299
- htlc_success_tx_weight(features)
300
- };
301
- // As required by the spec, round down
302
- feerate_per_kw as u64 * htlc_tx_weight / 1000
303
- };
304
- self.amount_msat / 1000 < broadcaster_dust_limit_sat + htlc_tx_fee_sat
305
- }
306
- }
307
-
308
287
#[cfg_attr(test, derive(Clone, Debug, PartialEq))]
309
288
enum OutboundHTLCState {
310
289
/// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we
@@ -430,27 +409,6 @@ struct OutboundHTLCOutput {
430
409
send_timestamp: Option<Duration>,
431
410
}
432
411
433
- impl OutboundHTLCOutput {
434
- fn is_dust(
435
- &self, local: bool, feerate_per_kw: u32, broadcaster_dust_limit_sat: u64,
436
- features: &ChannelTypeFeatures,
437
- ) -> bool {
438
- let htlc_tx_fee_sat = if features.supports_anchors_zero_fee_htlc_tx() {
439
- 0
440
- } else {
441
- let htlc_tx_weight = if local {
442
- // this is an offered htlc
443
- htlc_timeout_tx_weight(features)
444
- } else {
445
- htlc_success_tx_weight(features)
446
- };
447
- // As required by the spec, round down
448
- feerate_per_kw as u64 * htlc_tx_weight / 1000
449
- };
450
- self.amount_msat / 1000 < broadcaster_dust_limit_sat + htlc_tx_fee_sat
451
- }
452
- }
453
-
454
412
/// See AwaitingRemoteRevoke ChannelState for more info
455
413
#[cfg_attr(test, derive(Clone, Debug, PartialEq))]
456
414
enum HTLCUpdateAwaitingACK {
@@ -4378,14 +4336,9 @@ where
4378
4336
on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
4379
4337
return Err(LocalHTLCFailureReason::DustLimitCounterparty)
4380
4338
}
4381
- let htlc_success_dust_limit = if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
4382
- 0
4383
- } else {
4384
- let dust_buffer_feerate = self.get_dust_buffer_feerate(None) as u64;
4385
- dust_buffer_feerate * htlc_success_tx_weight(funding.get_channel_type()) / 1000
4386
- };
4387
- let exposure_dust_limit_success_sats = htlc_success_dust_limit + self.holder_dust_limit_satoshis;
4388
- if msg.amount_msat / 1000 < exposure_dust_limit_success_sats {
4339
+ let dust_buffer_feerate = self.get_dust_buffer_feerate(None);
4340
+ let (exposure_dust_limit_success_sat, _) = SpecTxBuilder {}.htlc_success_timeout_dust_limits(dust_buffer_feerate, self.holder_dust_limit_satoshis, funding.get_channel_type());
4341
+ if msg.amount_msat / 1000 < exposure_dust_limit_success_sat {
4389
4342
let on_holder_tx_dust_htlc_exposure_msat = htlc_stats.on_holder_tx_dust_exposure_msat;
4390
4343
if on_holder_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
4391
4344
log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx",
@@ -4466,10 +4419,11 @@ where
4466
4419
let mut value_to_remote_claimed_msat = 0;
4467
4420
4468
4421
let feerate_per_kw = feerate_per_kw.unwrap_or_else(|| self.get_commitment_feerate(funding, generated_by_local));
4422
+ let (dust_limit_success_sat, dust_limit_timeout_sat) = SpecTxBuilder {}.htlc_success_timeout_dust_limits(feerate_per_kw, broadcaster_dust_limit_sat, funding.get_channel_type());
4469
4423
4470
4424
for htlc in self.pending_inbound_htlcs.iter() {
4471
4425
if htlc.state.included_in_commitment(generated_by_local) {
4472
- if ! htlc.is_dust( local, feerate_per_kw, broadcaster_dust_limit_sat, funding.get_channel_type()) {
4426
+ if htlc.amount_msat >= if local { dust_limit_success_sat } else { dust_limit_timeout_sat } * 1000 {
4473
4427
nondust_htlc_count += 1;
4474
4428
}
4475
4429
remote_htlc_total_msat += htlc.amount_msat;
@@ -4482,7 +4436,7 @@ where
4482
4436
4483
4437
for htlc in self.pending_outbound_htlcs.iter() {
4484
4438
if htlc.state.included_in_commitment(generated_by_local) {
4485
- if ! htlc.is_dust( local, feerate_per_kw, broadcaster_dust_limit_sat, funding.get_channel_type()) {
4439
+ if htlc.amount_msat >= if local { dust_limit_timeout_sat } else { dust_limit_success_sat } * 1000 {
4486
4440
nondust_htlc_count += 1;
4487
4441
}
4488
4442
local_htlc_total_msat += htlc.amount_msat;
@@ -4707,15 +4661,10 @@ where
4707
4661
dust_exposure_limiting_feerate: u32,
4708
4662
) -> HTLCStats {
4709
4663
let context = self;
4710
- let uses_0_htlc_fee_anchors = funding.get_channel_type().supports_anchors_zero_fee_htlc_tx();
4711
4664
4712
4665
let dust_buffer_feerate = context.get_dust_buffer_feerate(outbound_feerate_update);
4713
- let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if uses_0_htlc_fee_anchors {
4714
- (0, 0)
4715
- } else {
4716
- (dust_buffer_feerate as u64 * htlc_timeout_tx_weight(funding.get_channel_type()) / 1000,
4717
- dust_buffer_feerate as u64 * htlc_success_tx_weight(funding.get_channel_type()) / 1000)
4718
- };
4666
+ let (counterparty_dust_limit_success_sat, counterparty_dust_limit_timeout_sat) = SpecTxBuilder {}.htlc_success_timeout_dust_limits(dust_buffer_feerate, context.counterparty_dust_limit_satoshis, funding.get_channel_type());
4667
+ let (holder_dust_limit_success_sat, holder_dust_limit_timeout_sat) = SpecTxBuilder {}.htlc_success_timeout_dust_limits(dust_buffer_feerate, context.holder_dust_limit_satoshis, funding.get_channel_type());
4719
4668
4720
4669
let mut on_holder_tx_dust_exposure_msat = 0;
4721
4670
let mut on_counterparty_tx_dust_exposure_msat = 0;
@@ -4726,8 +4675,6 @@ where
4726
4675
let mut pending_inbound_htlcs_value_msat = 0;
4727
4676
4728
4677
{
4729
- let counterparty_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.counterparty_dust_limit_satoshis;
4730
- let holder_dust_limit_success_sat = htlc_success_dust_limit + context.holder_dust_limit_satoshis;
4731
4678
for htlc in context.pending_inbound_htlcs.iter() {
4732
4679
pending_inbound_htlcs_value_msat += htlc.amount_msat;
4733
4680
if htlc.amount_msat / 1000 < counterparty_dust_limit_timeout_sat {
@@ -4746,8 +4693,6 @@ where
4746
4693
let mut on_holder_tx_outbound_holding_cell_htlcs_count = 0;
4747
4694
let mut pending_outbound_htlcs = self.pending_outbound_htlcs.len();
4748
4695
{
4749
- let counterparty_dust_limit_success_sat = htlc_success_dust_limit + context.counterparty_dust_limit_satoshis;
4750
- let holder_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.holder_dust_limit_satoshis;
4751
4696
for htlc in context.pending_outbound_htlcs.iter() {
4752
4697
pending_outbound_htlcs_value_msat += htlc.amount_msat;
4753
4698
if htlc.amount_msat / 1000 < counterparty_dust_limit_success_sat {
@@ -4786,10 +4731,10 @@ where
4786
4731
.checked_sub(dust_exposure_limiting_feerate);
4787
4732
let extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat = excess_feerate_opt.map(|excess_feerate| {
4788
4733
let extra_htlc_commit_tx_fee_sat = SpecTxBuilder {}.commit_tx_fee_sat(excess_feerate, on_counterparty_tx_accepted_nondust_htlcs + 1 + on_counterparty_tx_offered_nondust_htlcs, funding.get_channel_type());
4789
- let extra_htlc_htlc_tx_fees_sat = chan_utils::htlc_tx_fees_sat (excess_feerate, on_counterparty_tx_accepted_nondust_htlcs + 1, on_counterparty_tx_offered_nondust_htlcs, funding.get_channel_type());
4734
+ let extra_htlc_htlc_tx_fees_sat = SpecTxBuilder {}.htlc_txs_endogenous_fees_sat (excess_feerate, on_counterparty_tx_accepted_nondust_htlcs + 1, on_counterparty_tx_offered_nondust_htlcs, funding.get_channel_type());
4790
4735
4791
4736
let commit_tx_fee_sat = SpecTxBuilder {}.commit_tx_fee_sat(excess_feerate, on_counterparty_tx_accepted_nondust_htlcs + on_counterparty_tx_offered_nondust_htlcs, funding.get_channel_type());
4792
- let htlc_tx_fees_sat = chan_utils::htlc_tx_fees_sat (excess_feerate, on_counterparty_tx_accepted_nondust_htlcs, on_counterparty_tx_offered_nondust_htlcs, funding.get_channel_type());
4737
+ let htlc_tx_fees_sat = SpecTxBuilder {}.htlc_txs_endogenous_fees_sat (excess_feerate, on_counterparty_tx_accepted_nondust_htlcs, on_counterparty_tx_offered_nondust_htlcs, funding.get_channel_type());
4793
4738
4794
4739
let extra_htlc_dust_exposure = on_counterparty_tx_dust_exposure_msat + (extra_htlc_commit_tx_fee_sat + extra_htlc_htlc_tx_fees_sat) * 1000;
4795
4740
on_counterparty_tx_dust_exposure_msat += (commit_tx_fee_sat + htlc_tx_fees_sat) * 1000;
@@ -4838,13 +4783,8 @@ where
4838
4783
}
4839
4784
}
4840
4785
let mut inbound_details = Vec::new();
4841
- let htlc_success_dust_limit = if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
4842
- 0
4843
- } else {
4844
- let dust_buffer_feerate = self.get_dust_buffer_feerate(None) as u64;
4845
- dust_buffer_feerate * htlc_success_tx_weight(funding.get_channel_type()) / 1000
4846
- };
4847
- let holder_dust_limit_success_sat = htlc_success_dust_limit + self.holder_dust_limit_satoshis;
4786
+ let dust_buffer_feerate = self.get_dust_buffer_feerate(None);
4787
+ let (holder_dust_limit_success_sat, _) = SpecTxBuilder {}.htlc_success_timeout_dust_limits(dust_buffer_feerate, self.holder_dust_limit_satoshis, funding.get_channel_type());
4848
4788
for htlc in self.pending_inbound_htlcs.iter() {
4849
4789
if let Some(state_details) = (&htlc.state).into() {
4850
4790
inbound_details.push(InboundHTLCDetails{
@@ -4864,13 +4804,8 @@ where
4864
4804
#[rustfmt::skip]
4865
4805
pub fn get_pending_outbound_htlc_details(&self, funding: &FundingScope) -> Vec<OutboundHTLCDetails> {
4866
4806
let mut outbound_details = Vec::new();
4867
- let htlc_timeout_dust_limit = if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
4868
- 0
4869
- } else {
4870
- let dust_buffer_feerate = self.get_dust_buffer_feerate(None) as u64;
4871
- dust_buffer_feerate * htlc_success_tx_weight(funding.get_channel_type()) / 1000
4872
- };
4873
- let holder_dust_limit_timeout_sat = htlc_timeout_dust_limit + self.holder_dust_limit_satoshis;
4807
+ let dust_buffer_feerate = self.get_dust_buffer_feerate(None);
4808
+ let (_, holder_dust_limit_timeout_sat) = SpecTxBuilder {}.htlc_success_timeout_dust_limits(dust_buffer_feerate, self.holder_dust_limit_satoshis, funding.get_channel_type());
4874
4809
for htlc in self.pending_outbound_htlcs.iter() {
4875
4810
outbound_details.push(OutboundHTLCDetails{
4876
4811
htlc_id: Some(htlc.htlc_id),
@@ -4932,6 +4867,8 @@ where
4932
4867
4933
4868
let mut available_capacity_msat = outbound_capacity_msat;
4934
4869
4870
+ let (real_dust_limit_success_sat, real_dust_limit_timeout_sat) = SpecTxBuilder {}.htlc_success_timeout_dust_limits(context.feerate_per_kw, context.holder_dust_limit_satoshis, funding.get_channel_type());
4871
+
4935
4872
if funding.is_outbound() {
4936
4873
// We should mind channel commit tx fee when computing how much of the available capacity
4937
4874
// can be used in the next htlc. Mirrors the logic in send_htlc.
@@ -4940,10 +4877,6 @@ where
4940
4877
// and the answer will in turn change the amount itself — making it a circular
4941
4878
// dependency.
4942
4879
// This complicates the computation around dust-values, up to the one-htlc-value.
4943
- let mut real_dust_limit_timeout_sat = context.holder_dust_limit_satoshis;
4944
- if !funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
4945
- real_dust_limit_timeout_sat += context.feerate_per_kw as u64 * htlc_timeout_tx_weight(funding.get_channel_type()) / 1000;
4946
- }
4947
4880
4948
4881
let htlc_above_dust = HTLCCandidate::new(real_dust_limit_timeout_sat * 1000, HTLCInitiator::LocalOffered);
4949
4882
let mut max_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(funding, htlc_above_dust, Some(()));
@@ -4971,11 +4904,6 @@ where
4971
4904
} else {
4972
4905
// If the channel is inbound (i.e. counterparty pays the fee), we need to make sure
4973
4906
// sending a new HTLC won't reduce their balance below our reserve threshold.
4974
- let mut real_dust_limit_success_sat = context.counterparty_dust_limit_satoshis;
4975
- if !funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
4976
- real_dust_limit_success_sat += context.feerate_per_kw as u64 * htlc_success_tx_weight(funding.get_channel_type()) / 1000;
4977
- }
4978
-
4979
4907
let htlc_above_dust = HTLCCandidate::new(real_dust_limit_success_sat * 1000, HTLCInitiator::LocalOffered);
4980
4908
let max_reserved_commit_tx_fee_msat = context.next_remote_commit_tx_fee_msat(funding, Some(htlc_above_dust), None);
4981
4909
@@ -4997,13 +4925,9 @@ where
4997
4925
let mut dust_exposure_dust_limit_msat = 0;
4998
4926
let max_dust_htlc_exposure_msat = context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate);
4999
4927
5000
- let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
5001
- (context.counterparty_dust_limit_satoshis, context.holder_dust_limit_satoshis)
5002
- } else {
5003
- let dust_buffer_feerate = context.get_dust_buffer_feerate(None) as u64;
5004
- (context.counterparty_dust_limit_satoshis + dust_buffer_feerate * htlc_success_tx_weight(funding.get_channel_type()) / 1000,
5005
- context.holder_dust_limit_satoshis + dust_buffer_feerate * htlc_timeout_tx_weight(funding.get_channel_type()) / 1000)
5006
- };
4928
+ let dust_buffer_feerate = context.get_dust_buffer_feerate(None);
4929
+ let (htlc_success_dust_limit, _) = SpecTxBuilder {}.htlc_success_timeout_dust_limits(dust_buffer_feerate, context.counterparty_dust_limit_satoshis, funding.get_channel_type());
4930
+ let (_, htlc_timeout_dust_limit) = SpecTxBuilder {}.htlc_success_timeout_dust_limits(dust_buffer_feerate, context.holder_dust_limit_satoshis, funding.get_channel_type());
5007
4931
5008
4932
if let Some(extra_htlc_dust_exposure) = htlc_stats.extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat {
5009
4933
if extra_htlc_dust_exposure > max_dust_htlc_exposure_msat {
@@ -5069,14 +4993,7 @@ where
5069
4993
let context = self;
5070
4994
assert!(funding.is_outbound());
5071
4995
5072
- let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
5073
- (0, 0)
5074
- } else {
5075
- (context.feerate_per_kw as u64 * htlc_success_tx_weight(funding.get_channel_type()) / 1000,
5076
- context.feerate_per_kw as u64 * htlc_timeout_tx_weight(funding.get_channel_type()) / 1000)
5077
- };
5078
- let real_dust_limit_success_sat = htlc_success_dust_limit + context.holder_dust_limit_satoshis;
5079
- let real_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.holder_dust_limit_satoshis;
4996
+ let (real_dust_limit_success_sat, real_dust_limit_timeout_sat) = SpecTxBuilder {}.htlc_success_timeout_dust_limits(context.feerate_per_kw, context.holder_dust_limit_satoshis, funding.get_channel_type());
5080
4997
5081
4998
let mut addl_htlcs = 0;
5082
4999
if fee_spike_buffer_htlc.is_some() { addl_htlcs += 1; }
@@ -5178,14 +5095,7 @@ where
5178
5095
let context = self;
5179
5096
assert!(!funding.is_outbound());
5180
5097
5181
- let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
5182
- (0, 0)
5183
- } else {
5184
- (context.feerate_per_kw as u64 * htlc_success_tx_weight(funding.get_channel_type()) / 1000,
5185
- context.feerate_per_kw as u64 * htlc_timeout_tx_weight(funding.get_channel_type()) / 1000)
5186
- };
5187
- let real_dust_limit_success_sat = htlc_success_dust_limit + context.counterparty_dust_limit_satoshis;
5188
- let real_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.counterparty_dust_limit_satoshis;
5098
+ let (real_dust_limit_success_sat, real_dust_limit_timeout_sat) = SpecTxBuilder {}.htlc_success_timeout_dust_limits(context.feerate_per_kw, context.counterparty_dust_limit_satoshis, funding.get_channel_type());
5189
5099
5190
5100
let mut addl_htlcs = 0;
5191
5101
if fee_spike_buffer_htlc.is_some() { addl_htlcs += 1; }
0 commit comments