@@ -436,6 +436,21 @@ pub struct ChannelConfig {
436
436
/// [`PaymentClaimable::counterparty_skimmed_fee_msat`]: crate::events::Event::PaymentClaimable::counterparty_skimmed_fee_msat
437
437
// TODO: link to bLIP when it's merged
438
438
pub accept_underpaying_htlcs : bool ,
439
+ /// Similar to [`Self::max_dust_htlc_exposure_msat`], but instead of setting a fixed maximum,
440
+ /// this sets a multiplier on the estimated high priority feerate (sats/KW, as obtained from
441
+ /// [`FeeEstimator`]) to determine the maximum allowed dust exposure. If this field is set to
442
+ /// `Some(value)`, then the maximum dust exposure in sats is calculated as:
443
+ /// `high_priority_feerate_per_kw * value / 1000`.
444
+ ///
445
+ /// This allows the maximum dust exposure to automatically scale with fee rate changes. With
446
+ /// a fixed maximum, if the feerate increases significantly, then without a manually increase
447
+ /// to this maximum, the channel may be unable to send/receive HTLCs between the maximum dust
448
+ /// exposure and the new minimum value for HTLCs to be economically viable to claim.
449
+ ///
450
+ /// Default value: `Some(5000)`.
451
+ ///
452
+ /// [`FeeEstimator`]: crate::chain::chaininterface::FeeEstimator
453
+ pub max_dust_htlc_exposure_multiplier_thousandths : Option < u64 > ,
439
454
}
440
455
441
456
impl ChannelConfig {
@@ -456,6 +471,9 @@ impl ChannelConfig {
456
471
if let Some ( force_close_avoidance_max_fee_satoshis) = update. force_close_avoidance_max_fee_satoshis {
457
472
self . force_close_avoidance_max_fee_satoshis = force_close_avoidance_max_fee_satoshis;
458
473
}
474
+ if let Some ( max_dust_htlc_exposure_multiplier_thousandths) = update. max_dust_htlc_exposure_multiplier_thousandths {
475
+ self . max_dust_htlc_exposure_multiplier_thousandths = max_dust_htlc_exposure_multiplier_thousandths;
476
+ }
459
477
}
460
478
}
461
479
@@ -469,6 +487,7 @@ impl Default for ChannelConfig {
469
487
max_dust_htlc_exposure_msat : 5_000_000 ,
470
488
force_close_avoidance_max_fee_satoshis : 1000 ,
471
489
accept_underpaying_htlcs : false ,
490
+ max_dust_htlc_exposure_multiplier_thousandths : Some ( 5000 ) ,
472
491
}
473
492
}
474
493
}
@@ -483,6 +502,7 @@ impl_writeable_tlv_based!(ChannelConfig, {
483
502
// LegacyChannelConfig. To make sure that serialization is not compatible with this one, we use
484
503
// the next required type of 10, which if seen by the old serialization will always fail.
485
504
( 10 , force_close_avoidance_max_fee_satoshis, required) ,
505
+ ( 12 , max_dust_htlc_exposure_multiplier_thousandths, required)
486
506
} ) ;
487
507
488
508
/// A parallel struct to [`ChannelConfig`] to define partial updates.
@@ -493,6 +513,7 @@ pub struct ChannelConfigUpdate {
493
513
pub cltv_expiry_delta : Option < u16 > ,
494
514
pub max_dust_htlc_exposure_msat : Option < u64 > ,
495
515
pub force_close_avoidance_max_fee_satoshis : Option < u64 > ,
516
+ pub max_dust_htlc_exposure_multiplier_thousandths : Option < Option < u64 > > ,
496
517
}
497
518
498
519
impl Default for ChannelConfigUpdate {
@@ -503,6 +524,7 @@ impl Default for ChannelConfigUpdate {
503
524
cltv_expiry_delta : None ,
504
525
max_dust_htlc_exposure_msat : None ,
505
526
force_close_avoidance_max_fee_satoshis : None ,
527
+ max_dust_htlc_exposure_multiplier_thousandths : None ,
506
528
}
507
529
}
508
530
}
@@ -515,6 +537,7 @@ impl From<ChannelConfig> for ChannelConfigUpdate {
515
537
cltv_expiry_delta : Some ( config. cltv_expiry_delta ) ,
516
538
max_dust_htlc_exposure_msat : Some ( config. max_dust_htlc_exposure_msat ) ,
517
539
force_close_avoidance_max_fee_satoshis : Some ( config. force_close_avoidance_max_fee_satoshis ) ,
540
+ max_dust_htlc_exposure_multiplier_thousandths : Some ( config. max_dust_htlc_exposure_multiplier_thousandths ) ,
518
541
}
519
542
}
520
543
}
@@ -554,6 +577,7 @@ impl crate::util::ser::Writeable for LegacyChannelConfig {
554
577
( 4 , self . announced_channel, required) ,
555
578
( 6 , self . commit_upfront_shutdown_pubkey, required) ,
556
579
( 8 , self . options. forwarding_fee_base_msat, required) ,
580
+ ( 10 , self . options. max_dust_htlc_exposure_multiplier_thousandths, option) ,
557
581
} ) ;
558
582
Ok ( ( ) )
559
583
}
@@ -568,6 +592,7 @@ impl crate::util::ser::Readable for LegacyChannelConfig {
568
592
let mut announced_channel = false ;
569
593
let mut commit_upfront_shutdown_pubkey = false ;
570
594
let mut forwarding_fee_base_msat = 0 ;
595
+ let mut max_dust_htlc_exposure_multiplier_thousandths = None ;
571
596
read_tlv_fields ! ( reader, {
572
597
( 0 , forwarding_fee_proportional_millionths, required) ,
573
598
( 1 , max_dust_htlc_exposure_msat, ( default_value, 5_000_000u64 ) ) ,
@@ -576,6 +601,7 @@ impl crate::util::ser::Readable for LegacyChannelConfig {
576
601
( 4 , announced_channel, required) ,
577
602
( 6 , commit_upfront_shutdown_pubkey, required) ,
578
603
( 8 , forwarding_fee_base_msat, required) ,
604
+ ( 10 , max_dust_htlc_exposure_multiplier_thousandths, option) ,
579
605
} ) ;
580
606
Ok ( Self {
581
607
options : ChannelConfig {
@@ -585,6 +611,7 @@ impl crate::util::ser::Readable for LegacyChannelConfig {
585
611
force_close_avoidance_max_fee_satoshis,
586
612
forwarding_fee_base_msat,
587
613
accept_underpaying_htlcs : false ,
614
+ max_dust_htlc_exposure_multiplier_thousandths,
588
615
} ,
589
616
announced_channel,
590
617
commit_upfront_shutdown_pubkey,
0 commit comments