@@ -397,6 +397,21 @@ pub struct ChannelConfig {
397
397
/// [`Normal`]: crate::chain::chaininterface::ConfirmationTarget::Normal
398
398
/// [`Background`]: crate::chain::chaininterface::ConfirmationTarget::Background
399
399
pub force_close_avoidance_max_fee_satoshis : u64 ,
400
+ /// Similar to [`Self::max_dust_htlc_exposure_msat`], but instead of setting a fixed maximum,
401
+ /// this sets a multiplier on the estimated high priority feerate (sats/KW, as obtained from
402
+ /// [`FeeEstimator`]) to determine the maximum allowed dust exposure. If this field is set to
403
+ /// `Some(value)`, then the maximum dust exposure in sats is calculated as:
404
+ /// `high_priority_feerate_per_kw * value / 1000`.
405
+ ///
406
+ /// This allows the maximum dust exposure to automatically scale with fee rate changes. With
407
+ /// a fixed maximum, if the feerate increases significantly, then without a manually increase
408
+ /// to this maximum, the channel may be unable to send/receive HTLCs between the maximum dust
409
+ /// exposure and the new minimum value for HTLCs to be economically viable to claim.
410
+ ///
411
+ /// Default value: `Some(5000)`.
412
+ ///
413
+ /// [`FeeEstimator`]: crate::chain::chaininterface::FeeEstimator
414
+ pub max_dust_htlc_exposure_multiplier_thousandths : Option < u64 > ,
400
415
}
401
416
402
417
impl ChannelConfig {
@@ -417,6 +432,9 @@ impl ChannelConfig {
417
432
if let Some ( force_close_avoidance_max_fee_satoshis) = update. force_close_avoidance_max_fee_satoshis {
418
433
self . force_close_avoidance_max_fee_satoshis = force_close_avoidance_max_fee_satoshis;
419
434
}
435
+ if let Some ( max_dust_htlc_exposure_multiplier_thousandths) = update. max_dust_htlc_exposure_multiplier_thousandths {
436
+ self . max_dust_htlc_exposure_multiplier_thousandths = max_dust_htlc_exposure_multiplier_thousandths;
437
+ }
420
438
}
421
439
}
422
440
@@ -429,6 +447,7 @@ impl Default for ChannelConfig {
429
447
cltv_expiry_delta : 6 * 12 , // 6 blocks/hour * 12 hours
430
448
max_dust_htlc_exposure_msat : 5_000_000 ,
431
449
force_close_avoidance_max_fee_satoshis : 1000 ,
450
+ max_dust_htlc_exposure_multiplier_thousandths : Some ( 5000 ) ,
432
451
}
433
452
}
434
453
}
@@ -442,6 +461,7 @@ impl_writeable_tlv_based!(ChannelConfig, {
442
461
// LegacyChannelConfig. To make sure that serialization is not compatible with this one, we use
443
462
// the next required type of 10, which if seen by the old serialization will always fail.
444
463
( 10 , force_close_avoidance_max_fee_satoshis, required) ,
464
+ ( 12 , max_dust_htlc_exposure_multiplier_thousandths, required)
445
465
} ) ;
446
466
447
467
/// A parallel struct to [`ChannelConfig`] to define partial updates.
@@ -452,6 +472,7 @@ pub struct ChannelConfigUpdate {
452
472
pub cltv_expiry_delta : Option < u16 > ,
453
473
pub max_dust_htlc_exposure_msat : Option < u64 > ,
454
474
pub force_close_avoidance_max_fee_satoshis : Option < u64 > ,
475
+ pub max_dust_htlc_exposure_multiplier_thousandths : Option < Option < u64 > > ,
455
476
}
456
477
457
478
impl Default for ChannelConfigUpdate {
@@ -462,6 +483,7 @@ impl Default for ChannelConfigUpdate {
462
483
cltv_expiry_delta : None ,
463
484
max_dust_htlc_exposure_msat : None ,
464
485
force_close_avoidance_max_fee_satoshis : None ,
486
+ max_dust_htlc_exposure_multiplier_thousandths : None ,
465
487
}
466
488
}
467
489
}
@@ -474,6 +496,7 @@ impl From<ChannelConfig> for ChannelConfigUpdate {
474
496
cltv_expiry_delta : Some ( config. cltv_expiry_delta ) ,
475
497
max_dust_htlc_exposure_msat : Some ( config. max_dust_htlc_exposure_msat ) ,
476
498
force_close_avoidance_max_fee_satoshis : Some ( config. force_close_avoidance_max_fee_satoshis ) ,
499
+ max_dust_htlc_exposure_multiplier_thousandths : Some ( config. max_dust_htlc_exposure_multiplier_thousandths ) ,
477
500
}
478
501
}
479
502
}
@@ -513,6 +536,7 @@ impl crate::util::ser::Writeable for LegacyChannelConfig {
513
536
( 4 , self . announced_channel, required) ,
514
537
( 6 , self . commit_upfront_shutdown_pubkey, required) ,
515
538
( 8 , self . options. forwarding_fee_base_msat, required) ,
539
+ ( 10 , self . options. max_dust_htlc_exposure_multiplier_thousandths, option) ,
516
540
} ) ;
517
541
Ok ( ( ) )
518
542
}
@@ -527,6 +551,7 @@ impl crate::util::ser::Readable for LegacyChannelConfig {
527
551
let mut announced_channel = false ;
528
552
let mut commit_upfront_shutdown_pubkey = false ;
529
553
let mut forwarding_fee_base_msat = 0 ;
554
+ let mut max_dust_htlc_exposure_multiplier_thousandths = None ;
530
555
read_tlv_fields ! ( reader, {
531
556
( 0 , forwarding_fee_proportional_millionths, required) ,
532
557
( 1 , max_dust_htlc_exposure_msat, ( default_value, 5_000_000u64 ) ) ,
@@ -535,6 +560,7 @@ impl crate::util::ser::Readable for LegacyChannelConfig {
535
560
( 4 , announced_channel, required) ,
536
561
( 6 , commit_upfront_shutdown_pubkey, required) ,
537
562
( 8 , forwarding_fee_base_msat, required) ,
563
+ ( 10 , max_dust_htlc_exposure_multiplier_thousandths, option) ,
538
564
} ) ;
539
565
Ok ( Self {
540
566
options : ChannelConfig {
@@ -543,6 +569,7 @@ impl crate::util::ser::Readable for LegacyChannelConfig {
543
569
cltv_expiry_delta,
544
570
force_close_avoidance_max_fee_satoshis,
545
571
forwarding_fee_base_msat,
572
+ max_dust_htlc_exposure_multiplier_thousandths,
546
573
} ,
547
574
announced_channel,
548
575
commit_upfront_shutdown_pubkey,
0 commit comments