13
13
14
14
use crate::chain;
15
15
use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch};
16
- use crate :: chain:: chaininterface:: LowerBoundedFeeEstimator ;
16
+ use crate::chain::chaininterface::{ LowerBoundedFeeEstimator, FeeEstimator, ConfirmationTarget} ;
17
17
use crate::chain::channelmonitor;
18
18
use crate::chain::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
19
19
use crate::chain::transaction::OutPoint;
@@ -9565,7 +9565,7 @@ enum ExposureEvent {
9565
9565
AtUpdateFeeOutbound,
9566
9566
}
9567
9567
9568
- fn do_test_max_dust_htlc_exposure ( dust_outbound_balance : bool , exposure_breach_event : ExposureEvent , on_holder_tx : bool ) {
9568
+ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_event: ExposureEvent, on_holder_tx: bool, multiplier_dust_limit: bool ) {
9569
9569
// Test that we properly reject dust HTLC violating our `max_dust_htlc_exposure_msat`
9570
9570
// policy.
9571
9571
//
@@ -9581,6 +9581,9 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
9581
9581
let chanmon_cfgs = create_chanmon_cfgs(2);
9582
9582
let mut config = test_default_channel_config();
9583
9583
config.channel_config.max_dust_htlc_exposure_msat = 5_000_000; // default setting value
9584
+ // Default test fee estimator rate is 253 sat/kw, so we set the multiplier to 5_000_000 / 253
9585
+ // to get roughly the same initial value as the default setting.
9586
+ config.channel_config.max_dust_htlc_exposure_multiplier_thousandths = if multiplier_dust_limit { Some(5_000_000 / 253) } else { None };
9584
9587
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
9585
9588
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config), None]);
9586
9589
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
@@ -9630,14 +9633,21 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
9630
9633
let chan = chan_lock.channel_by_id.get(&channel_id).unwrap();
9631
9634
chan.get_dust_buffer_feerate(None) as u64
9632
9635
};
9636
+ let max_dust_htlc_exposure_msat = if multiplier_dust_limit {
9637
+ nodes[0].fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) as u64
9638
+ * config.channel_config.max_dust_htlc_exposure_multiplier_thousandths.unwrap()
9639
+ } else {
9640
+ config.channel_config.max_dust_htlc_exposure_msat
9641
+ };
9642
+
9633
9643
let dust_outbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_timeout_tx_weight(opt_anchors) / 1000 + open_channel.dust_limit_satoshis - 1) * 1000;
9634
- let dust_outbound_htlc_on_holder_tx: u64 = config . channel_config . max_dust_htlc_exposure_msat / dust_outbound_htlc_on_holder_tx_msat;
9644
+ let dust_outbound_htlc_on_holder_tx: u64 = max_dust_htlc_exposure_msat / dust_outbound_htlc_on_holder_tx_msat;
9635
9645
9636
9646
let dust_inbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_success_tx_weight(opt_anchors) / 1000 + open_channel.dust_limit_satoshis - 1) * 1000;
9637
- let dust_inbound_htlc_on_holder_tx: u64 = config . channel_config . max_dust_htlc_exposure_msat / dust_inbound_htlc_on_holder_tx_msat;
9647
+ let dust_inbound_htlc_on_holder_tx: u64 = max_dust_htlc_exposure_msat / dust_inbound_htlc_on_holder_tx_msat;
9638
9648
9639
9649
let dust_htlc_on_counterparty_tx: u64 = 4;
9640
- let dust_htlc_on_counterparty_tx_msat: u64 = config . channel_config . max_dust_htlc_exposure_msat / dust_htlc_on_counterparty_tx;
9650
+ let dust_htlc_on_counterparty_tx_msat: u64 = max_dust_htlc_exposure_msat / dust_htlc_on_counterparty_tx;
9641
9651
9642
9652
if on_holder_tx {
9643
9653
if dust_outbound_balance {
@@ -9689,7 +9699,7 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
9689
9699
), true, APIError::ChannelUnavailable { .. }, {});
9690
9700
}
9691
9701
} else if exposure_breach_event == ExposureEvent::AtHTLCReception {
9692
- let ( route, payment_hash, _, payment_secret) = get_route_and_payment_hash ! ( nodes[ 1 ] , nodes[ 0 ] , if on_holder_tx { dust_inbound_htlc_on_holder_tx_msat } else { dust_htlc_on_counterparty_tx_msat + 1 } ) ;
9702
+ let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], if on_holder_tx { dust_inbound_htlc_on_holder_tx_msat } else { dust_htlc_on_counterparty_tx_msat + 4 });
9693
9703
nodes[1].node.send_payment_with_route(&route, payment_hash,
9694
9704
RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
9695
9705
check_added_monitors!(nodes[1], 1);
@@ -9702,18 +9712,24 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
9702
9712
// Outbound dust balance: 6399 sats
9703
9713
let dust_inbound_overflow = dust_inbound_htlc_on_holder_tx_msat * (dust_inbound_htlc_on_holder_tx + 1);
9704
9714
let dust_outbound_overflow = dust_outbound_htlc_on_holder_tx_msat * dust_outbound_htlc_on_holder_tx + dust_inbound_htlc_on_holder_tx_msat;
9705
- nodes[ 0 ] . logger . assert_log ( "lightning::ln::channel" . to_string ( ) , format ! ( "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx" , if dust_outbound_balance { dust_outbound_overflow } else { dust_inbound_overflow } , config . channel_config . max_dust_htlc_exposure_msat) , 1 ) ;
9715
+ nodes[0].logger.assert_log("lightning::ln::channel".to_string(), format!("Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx", if dust_outbound_balance { dust_outbound_overflow } else { dust_inbound_overflow }, max_dust_htlc_exposure_msat), 1);
9706
9716
} else {
9707
9717
// Outbound dust balance: 5200 sats
9708
9718
nodes[0].logger.assert_log("lightning::ln::channel".to_string(),
9709
9719
format!("Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx",
9710
- dust_htlc_on_counterparty_tx_msat * ( dust_htlc_on_counterparty_tx - 1 ) + dust_htlc_on_counterparty_tx_msat + 1 ,
9711
- config . channel_config . max_dust_htlc_exposure_msat) , 1 ) ;
9720
+ dust_htlc_on_counterparty_tx_msat * (dust_htlc_on_counterparty_tx - 1) + dust_htlc_on_counterparty_tx_msat + 4 ,
9721
+ max_dust_htlc_exposure_msat), 1);
9712
9722
}
9713
9723
} else if exposure_breach_event == ExposureEvent::AtUpdateFeeOutbound {
9714
9724
route.paths[0].hops.last_mut().unwrap().fee_msat = 2_500_000;
9715
- nodes[ 0 ] . node . send_payment_with_route ( & route, payment_hash,
9716
- RecipientOnionFields :: secret_only ( payment_secret) , PaymentId ( payment_hash. 0 ) ) . unwrap ( ) ;
9725
+ // For the multiplier dust exposure limit, since it scales with feerate,
9726
+ // we need to add a lot of HTLCs that will become dust at the new feerate
9727
+ // to cross the threshold.
9728
+ for _ in 0..20 {
9729
+ let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(1_000), None);
9730
+ nodes[0].node.send_payment_with_route(&route, payment_hash,
9731
+ RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
9732
+ }
9717
9733
{
9718
9734
let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
9719
9735
*feerate_lock = *feerate_lock * 10;
@@ -9728,20 +9744,25 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
9728
9744
added_monitors.clear();
9729
9745
}
9730
9746
9747
+ fn do_test_max_dust_htlc_exposure_by_threshold_type(multiplier_dust_limit: bool) {
9748
+ do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCForward, true, multiplier_dust_limit);
9749
+ do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCForward, true, multiplier_dust_limit);
9750
+ do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCReception, true, multiplier_dust_limit);
9751
+ do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCReception, false, multiplier_dust_limit);
9752
+ do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCForward, false, multiplier_dust_limit);
9753
+ do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCReception, false, multiplier_dust_limit);
9754
+ do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCReception, true, multiplier_dust_limit);
9755
+ do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCForward, false, multiplier_dust_limit);
9756
+ do_test_max_dust_htlc_exposure(true, ExposureEvent::AtUpdateFeeOutbound, true, multiplier_dust_limit);
9757
+ do_test_max_dust_htlc_exposure(true, ExposureEvent::AtUpdateFeeOutbound, false, multiplier_dust_limit);
9758
+ do_test_max_dust_htlc_exposure(false, ExposureEvent::AtUpdateFeeOutbound, false, multiplier_dust_limit);
9759
+ do_test_max_dust_htlc_exposure(false, ExposureEvent::AtUpdateFeeOutbound, true, multiplier_dust_limit);
9760
+ }
9761
+
9731
9762
#[test]
9732
9763
fn test_max_dust_htlc_exposure() {
9733
- do_test_max_dust_htlc_exposure ( true , ExposureEvent :: AtHTLCForward , true ) ;
9734
- do_test_max_dust_htlc_exposure ( false , ExposureEvent :: AtHTLCForward , true ) ;
9735
- do_test_max_dust_htlc_exposure ( false , ExposureEvent :: AtHTLCReception , true ) ;
9736
- do_test_max_dust_htlc_exposure ( false , ExposureEvent :: AtHTLCReception , false ) ;
9737
- do_test_max_dust_htlc_exposure ( true , ExposureEvent :: AtHTLCForward , false ) ;
9738
- do_test_max_dust_htlc_exposure ( true , ExposureEvent :: AtHTLCReception , false ) ;
9739
- do_test_max_dust_htlc_exposure ( true , ExposureEvent :: AtHTLCReception , true ) ;
9740
- do_test_max_dust_htlc_exposure ( false , ExposureEvent :: AtHTLCForward , false ) ;
9741
- do_test_max_dust_htlc_exposure ( true , ExposureEvent :: AtUpdateFeeOutbound , true ) ;
9742
- do_test_max_dust_htlc_exposure ( true , ExposureEvent :: AtUpdateFeeOutbound , false ) ;
9743
- do_test_max_dust_htlc_exposure ( false , ExposureEvent :: AtUpdateFeeOutbound , false ) ;
9744
- do_test_max_dust_htlc_exposure ( false , ExposureEvent :: AtUpdateFeeOutbound , true ) ;
9764
+ do_test_max_dust_htlc_exposure_by_threshold_type(false);
9765
+ do_test_max_dust_htlc_exposure_by_threshold_type(true);
9745
9766
}
9746
9767
9747
9768
#[test]
0 commit comments