From 8e7b1e0f553eece98b8899abb4b4efacb75cbf71 Mon Sep 17 00:00:00 2001 From: elnosh Date: Tue, 30 Sep 2025 10:33:35 -0400 Subject: [PATCH] ln-resource-mgr: increase opportunity cost gradually --- ln-resource-mgr/src/htlc_manager.rs | 6 +++++- ln-resource-mgr/src/outgoing_channel.rs | 20 ++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/ln-resource-mgr/src/htlc_manager.rs b/ln-resource-mgr/src/htlc_manager.rs index 0c0a00aa..50bfe6c5 100644 --- a/ln-resource-mgr/src/htlc_manager.rs +++ b/ln-resource-mgr/src/htlc_manager.rs @@ -32,7 +32,11 @@ impl ReputationParams { /// Calculates the opportunity_cost of a htlc being held on our channel - allowing one [`reputation_period`]'s /// grace period, then charging for every subsequent period. pub(super) fn opportunity_cost(&self, fee_msat: u64, hold_time: Duration) -> u64 { - (hold_time.as_secs() / self.resolution_period.as_secs()).saturating_mul(fee_msat) + (0_f64.max( + (hold_time.as_secs_f64() - self.resolution_period.as_secs_f64()) + / self.resolution_period.as_secs_f64(), + ) * (fee_msat as f64)) + .round() as u64 } /// Calculates the worst case reputation damage of a htlc, assuming it'll be held for its full expiry_delta. diff --git a/ln-resource-mgr/src/outgoing_channel.rs b/ln-resource-mgr/src/outgoing_channel.rs index 1f5faa77..0df9a146 100644 --- a/ln-resource-mgr/src/outgoing_channel.rs +++ b/ln-resource-mgr/src/outgoing_channel.rs @@ -137,12 +137,13 @@ mod tests { // Less than resolution_period has zero cost. assert_eq!(params.opportunity_cost(100, Duration::from_secs(10)), 0); - // Equal to resolution_period or within one period is equal to fee. - assert_eq!(params.opportunity_cost(100, Duration::from_secs(60)), 100); - assert_eq!(params.opportunity_cost(100, Duration::from_secs(65)), 100); + // Above resolution period it is gradually incremented. + assert_eq!(params.opportunity_cost(100, Duration::from_secs(61)), 2); + assert_eq!(params.opportunity_cost(100, Duration::from_secs(90)), 50); + assert_eq!(params.opportunity_cost(100, Duration::from_secs(120)), 100); // Multiple periods above resolution_period charges multiples of fee. - assert_eq!(params.opportunity_cost(100, Duration::from_secs(600)), 1000); + assert_eq!(params.opportunity_cost(100, Duration::from_secs(600)), 900); } #[test] @@ -164,7 +165,14 @@ mod tests { slow_resolve, AccountableSignal::Accountable, true, - Ok(-2000), + Ok(-1000), + ), + ( + 1000, + Duration::from_secs(90), + AccountableSignal::Accountable, + true, + Ok(500), ), ( 1000, @@ -178,7 +186,7 @@ mod tests { slow_resolve, AccountableSignal::Accountable, false, - Ok(-3000), + Ok(-2000), ), ( 1000,