X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Frouter.rs;h=cffd9ddb0a581ea2e26a53ee3f305a8c7f81bbf7;hb=49c9f1885dd7a564c0c78ad5f73ea4792c0171a8;hp=9e31d9ea5e734a3746486b07d5a27415bfccd7b0;hpb=81afc2f1729b2abf5eaa54c5da12f517349486a7;p=rust-lightning diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 9e31d9ea..cffd9ddb 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -29,6 +29,49 @@ use alloc::collections::BinaryHeap; use core::cmp; use core::ops::Deref; +/// A trait defining behavior for routing a payment. +pub trait Router { + /// Finds a [`Route`] between `payer` and `payee` for a payment with the given values. + fn find_route( + &self, payer: &PublicKey, route_params: &RouteParameters, + first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: InFlightHtlcs + ) -> Result; +} + +/// A map with liquidity value (in msat) keyed by a short channel id and the direction the HTLC +/// is traveling in. The direction boolean is determined by checking if the HTLC source's public +/// key is less than its destination. See [`InFlightHtlcs::used_liquidity_msat`] for more +/// details. +#[cfg(not(any(test, feature = "_test_utils")))] +pub struct InFlightHtlcs(HashMap<(u64, bool), u64>); +#[cfg(any(test, feature = "_test_utils"))] +pub struct InFlightHtlcs(pub HashMap<(u64, bool), u64>); + +impl InFlightHtlcs { + /// Create a new `InFlightHtlcs` via a mapping from: + /// (short_channel_id, source_pubkey < target_pubkey) -> used_liquidity_msat + pub fn new(inflight_map: HashMap<(u64, bool), u64>) -> Self { + InFlightHtlcs(inflight_map) + } + + /// Returns liquidity in msat given the public key of the HTLC source, target, and short channel + /// id. + pub fn used_liquidity_msat(&self, source: &NodeId, target: &NodeId, channel_scid: u64) -> Option { + self.0.get(&(channel_scid, source < target)).map(|v| *v) + } +} + +impl Writeable for InFlightHtlcs { + fn write(&self, writer: &mut W) -> Result<(), io::Error> { self.0.write(writer) } +} + +impl Readable for InFlightHtlcs { + fn read(reader: &mut R) -> Result { + let infight_map: HashMap<(u64, bool), u64> = Readable::read(reader)?; + Ok(Self(infight_map)) + } +} + /// A hop in a route #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct RouteHop { @@ -185,8 +228,7 @@ pub const DEFAULT_MAX_PATH_COUNT: u8 = 10; const MEDIAN_HOP_CLTV_EXPIRY_DELTA: u32 = 40; // During routing, we only consider paths shorter than our maximum length estimate. -// In the legacy onion format, the maximum number of hops used to be a fixed value of 20. -// However, in the TLV onion format, there is no fixed maximum length, but the `hop_payloads` +// In the TLV onion format, there is no fixed maximum length, but the `hop_payloads` // field is always 1300 bytes. As the `tlv_payload` for each hop may vary in length, we have to // estimate how many hops the route may have so that it actually fits the `hop_payloads` field. // @@ -494,10 +536,8 @@ fn max_htlc_from_capacity(capacity: EffectiveCapacity, max_channel_saturation_po EffectiveCapacity::Unknown => EffectiveCapacity::Unknown.as_msat(), EffectiveCapacity::MaximumHTLC { amount_msat } => amount_msat.checked_shr(saturation_shift).unwrap_or(0), - EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat: None } => - capacity_msat.checked_shr(saturation_shift).unwrap_or(0), - EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat: Some(htlc_max) } => - cmp::min(capacity_msat.checked_shr(saturation_shift).unwrap_or(0), htlc_max), + EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat } => + cmp::min(capacity_msat.checked_shr(saturation_shift).unwrap_or(0), htlc_maximum_msat), } } @@ -5391,7 +5431,7 @@ mod tests { let usage = ChannelUsage { amount_msat: 0, inflight_htlc_msat: 0, - effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: Some(1_000) }, + effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_000 }, }; scorer.set_manual_penalty(&NodeId::from_pubkey(&nodes[3]), 123); scorer.set_manual_penalty(&NodeId::from_pubkey(&nodes[4]), 456);