Skip to content

Commit 05d2ec7

Browse files
committed
Add BucketResources to resource manager
Resources available in the channel will be divided into general, congestion and protected resources. Here we implement the bucket resources that will be used for congestion and protected.
1 parent b8f0d49 commit 05d2ec7

1 file changed

Lines changed: 105 additions & 1 deletion

File tree

lightning/src/ln/resource_manager.rs

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,55 @@ fn assign_slots_for_channel(
211211
Ok(channel_slots)
212212
}
213213

214+
struct BucketResources {
215+
slots_allocated: u16,
216+
slots_used: u16,
217+
liquidity_allocated: u64,
218+
liquidity_used: u64,
219+
}
220+
221+
impl BucketResources {
222+
fn new(slots_allocated: u16, liquidity_allocated: u64) -> Self {
223+
BucketResources { slots_allocated, slots_used: 0, liquidity_allocated, liquidity_used: 0 }
224+
}
225+
226+
fn resources_available(&self, htlc_amount_msat: u64) -> bool {
227+
return (self.liquidity_used + htlc_amount_msat <= self.liquidity_allocated)
228+
&& (self.slots_used < self.slots_allocated);
229+
}
230+
231+
fn add_htlc(&mut self, htlc_amount_msat: u64) -> Result<(), ()> {
232+
if !self.resources_available(htlc_amount_msat) {
233+
return Err(());
234+
}
235+
236+
self.slots_used += 1;
237+
self.liquidity_used += htlc_amount_msat;
238+
debug_assert!(
239+
self.slots_used <= self.slots_allocated,
240+
"slots_used {} exceeded slots_allocated {}",
241+
self.slots_used,
242+
self.slots_allocated
243+
);
244+
debug_assert!(
245+
self.liquidity_used <= self.liquidity_allocated,
246+
"liquidity_used {} exceeded liquidity_allocated {}",
247+
self.liquidity_used,
248+
self.liquidity_allocated
249+
);
250+
Ok(())
251+
}
252+
253+
fn remove_htlc(&mut self, htlc_amount_msat: u64) -> Result<(), ()> {
254+
if self.slots_used == 0 || self.liquidity_used < htlc_amount_msat {
255+
return Err(());
256+
}
257+
self.slots_used -= 1;
258+
self.liquidity_used -= htlc_amount_msat;
259+
Ok(())
260+
}
261+
}
262+
214263
/// A weighted average that decays over a specified window.
215264
///
216265
/// It enables tracking of historical behavior without storing individual data points.
@@ -303,7 +352,8 @@ mod tests {
303352
use crate::{
304353
crypto::chacha20::ChaCha20,
305354
ln::resource_manager::{
306-
assign_slots_for_channel, AggregatedWindowAverage, DecayingAverage, GeneralBucket,
355+
assign_slots_for_channel, AggregatedWindowAverage, BucketResources, DecayingAverage,
356+
GeneralBucket,
307357
},
308358
sign::EntropySource,
309359
util::test_utils::TestKeysInterface,
@@ -469,6 +519,60 @@ mod tests {
469519
assert!(general_bucket.slots_occupied[slot_occupied as usize].is_none());
470520
}
471521

522+
fn test_bucket_resources() -> BucketResources {
523+
BucketResources {
524+
slots_allocated: 10,
525+
slots_used: 0,
526+
liquidity_allocated: 100_000,
527+
liquidity_used: 0,
528+
}
529+
}
530+
531+
#[test]
532+
fn test_bucket_resources_add_htlc() {
533+
let mut bucket_resources = test_bucket_resources();
534+
let available_liquidity = bucket_resources.liquidity_allocated;
535+
assert!(bucket_resources.add_htlc(available_liquidity + 1000).is_err());
536+
537+
assert!(bucket_resources.add_htlc(21_000).is_ok());
538+
assert!(bucket_resources.add_htlc(42_000).is_ok());
539+
assert_eq!(bucket_resources.slots_used, 2);
540+
assert_eq!(bucket_resources.liquidity_used, 63_000);
541+
}
542+
543+
#[test]
544+
fn test_bucket_resources_add_htlc_over_resources_available() {
545+
// Test trying to go over slot limit
546+
let mut bucket_resources = test_bucket_resources();
547+
let slots_available = bucket_resources.slots_allocated;
548+
for _ in 0..slots_available {
549+
assert!(bucket_resources.add_htlc(10).is_ok());
550+
}
551+
assert_eq!(bucket_resources.slots_used, slots_available);
552+
assert!(bucket_resources.add_htlc(10).is_err());
553+
554+
// Test trying to go over liquidity limit
555+
let mut bucket = test_bucket_resources();
556+
assert!(bucket.add_htlc(bucket.liquidity_allocated - 1000).is_ok());
557+
assert!(bucket.add_htlc(2000).is_err());
558+
}
559+
560+
#[test]
561+
fn test_bucket_resources_remove_htlc() {
562+
let mut bucket_resources = test_bucket_resources();
563+
564+
// If no resources have been used, removing HTLC should fail
565+
assert!(bucket_resources.remove_htlc(100).is_err());
566+
567+
bucket_resources.add_htlc(1000).unwrap();
568+
// Test failure if it tries to remove amount over what is currently in use.
569+
assert!(bucket_resources.remove_htlc(1001).is_err());
570+
571+
assert!(bucket_resources.remove_htlc(1000).is_ok());
572+
assert_eq!(bucket_resources.slots_used, 0);
573+
assert_eq!(bucket_resources.liquidity_used, 0);
574+
}
575+
472576
#[test]
473577
fn test_decaying_average_bounds() {
474578
for (start, bound) in [(1000, i64::MAX), (-1000, i64::MIN)] {

0 commit comments

Comments
 (0)