|
56 | 56 |
|
57 | 57 | use crate::ln::msgs::DecodeError;
|
58 | 58 | use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId};
|
59 |
| -use crate::routing::router::RouteHop; |
| 59 | +use crate::routing::router::{InFlightHtlcs, RouteHop}; |
60 | 60 | use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
|
61 | 61 | use crate::util::logger::Logger;
|
62 | 62 | use crate::util::time::Time;
|
@@ -316,6 +316,72 @@ impl ReadableArgs<u64> for FixedPenaltyScorer {
|
316 | 316 | }
|
317 | 317 | }
|
318 | 318 |
|
| 319 | +/// [`Score`] implementation that factors in in-flight HTLC liquidity. |
| 320 | +/// |
| 321 | +/// Useful for custom [`Router`] implementations to wrap their [`Score`] on-the-fly when calling |
| 322 | +/// [`find_route`]. |
| 323 | +/// |
| 324 | +/// Not to be used in conjunction with [`DefaultRouter`] because `DefaultRouter` automatically wraps |
| 325 | +/// its scorer with a `ScorerAccountingForInFlightHtlcs` when finding a route. |
| 326 | +/// |
| 327 | +/// [`DefaultRouter`]: crate::routing::router::DefaultRouter |
| 328 | +/// [`Router`]: crate::routing::router::Router |
| 329 | +/// [`find_route`]: crate::routing::router::find_route |
| 330 | +pub struct ScorerAccountingForInFlightHtlcs<'a, S: Score> |
| 331 | +{ |
| 332 | + scorer: &'a mut S, |
| 333 | + // Maps a channel's short channel id and its direction to the liquidity used up. |
| 334 | + inflight_htlcs: InFlightHtlcs, |
| 335 | +} |
| 336 | + |
| 337 | +impl<'a, S: Score> ScorerAccountingForInFlightHtlcs<'a, S> { |
| 338 | + /// Initialize a new `ScorerAccountingForInFlightHtlcs`. |
| 339 | + pub fn new(scorer: &'a mut S, inflight_htlcs: InFlightHtlcs) -> Self { |
| 340 | + ScorerAccountingForInFlightHtlcs { |
| 341 | + scorer, |
| 342 | + inflight_htlcs |
| 343 | + } |
| 344 | + } |
| 345 | +} |
| 346 | + |
| 347 | +#[cfg(c_bindings)] |
| 348 | +impl<'a, S:Score> crate::util::ser::Writeable for ScorerAccountingForInFlightHtlcs<'a, S> { |
| 349 | + fn write<W: crate::util::ser::Writer>(&self, writer: &mut W) -> Result<(), crate::io::Error> { self.scorer.write(writer) } |
| 350 | +} |
| 351 | + |
| 352 | +impl<'a, S: Score> Score for ScorerAccountingForInFlightHtlcs<'a, S> { |
| 353 | + fn channel_penalty_msat(&self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage) -> u64 { |
| 354 | + if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity_msat( |
| 355 | + source, target, short_channel_id |
| 356 | + ) { |
| 357 | + let usage = ChannelUsage { |
| 358 | + inflight_htlc_msat: usage.inflight_htlc_msat + used_liquidity, |
| 359 | + ..usage |
| 360 | + }; |
| 361 | + |
| 362 | + self.scorer.channel_penalty_msat(short_channel_id, source, target, usage) |
| 363 | + } else { |
| 364 | + self.scorer.channel_penalty_msat(short_channel_id, source, target, usage) |
| 365 | + } |
| 366 | + } |
| 367 | + |
| 368 | + fn payment_path_failed(&mut self, path: &[&RouteHop], short_channel_id: u64) { |
| 369 | + self.scorer.payment_path_failed(path, short_channel_id) |
| 370 | + } |
| 371 | + |
| 372 | + fn payment_path_successful(&mut self, path: &[&RouteHop]) { |
| 373 | + self.scorer.payment_path_successful(path) |
| 374 | + } |
| 375 | + |
| 376 | + fn probe_failed(&mut self, path: &[&RouteHop], short_channel_id: u64) { |
| 377 | + self.scorer.probe_failed(path, short_channel_id) |
| 378 | + } |
| 379 | + |
| 380 | + fn probe_successful(&mut self, path: &[&RouteHop]) { |
| 381 | + self.scorer.probe_successful(path) |
| 382 | + } |
| 383 | +} |
| 384 | + |
319 | 385 | #[cfg(not(feature = "no-std"))]
|
320 | 386 | type ConfiguredTime = std::time::Instant;
|
321 | 387 | #[cfg(feature = "no-std")]
|
|
0 commit comments