X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Frouter.rs;h=0a09ca81e3ffc6c13feca2c34391cac981128d62;hb=5824e226cad67e32d5e8be71ebbb6f91a3fc2116;hp=fa841d892313b064691d9e11e2f7686a70427610;hpb=3f9868f2350db93e2f5256aee2112ccabf1b531a;p=rust-lightning diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index fa841d89..0a09ca81 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -13,35 +13,98 @@ //! interrogate it to get routes for your own payments. use bitcoin::secp256k1::PublicKey; +use bitcoin::hashes::Hash; +use bitcoin::hashes::sha256::Hash as Sha256; use crate::ln::PaymentHash; use crate::ln::channelmanager::{ChannelDetails, PaymentId}; use crate::ln::features::{ChannelFeatures, InvoiceFeatures, NodeFeatures}; use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT}; use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId, RoutingFees}; -use crate::routing::scoring::{ChannelUsage, Score}; +use crate::routing::scoring::{ChannelUsage, LockableScore, Score}; use crate::util::ser::{Writeable, Readable, Writer}; use crate::util::logger::{Level, Logger}; use crate::util::chacha20::ChaCha20; use crate::io; use crate::prelude::*; +use crate::sync::Mutex; use alloc::collections::BinaryHeap; use core::cmp; use core::ops::Deref; +/// A [`Router`] implemented using [`find_route`]. +pub struct DefaultRouter>, L: Deref, S: Deref> where + L::Target: Logger, + S::Target: for <'a> LockableScore<'a>, +{ + network_graph: G, + logger: L, + random_seed_bytes: Mutex<[u8; 32]>, + scorer: S +} + +impl>, L: Deref, S: Deref> DefaultRouter where + L::Target: Logger, + S::Target: for <'a> LockableScore<'a>, +{ + /// Creates a new router. + pub fn new(network_graph: G, logger: L, random_seed_bytes: [u8; 32], scorer: S) -> Self { + let random_seed_bytes = Mutex::new(random_seed_bytes); + Self { network_graph, logger, random_seed_bytes, scorer } + } +} + +impl>, L: Deref, S: Deref> Router for DefaultRouter where + L::Target: Logger, + S::Target: for <'a> LockableScore<'a>, +{ + fn find_route( + &self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&ChannelDetails]>, + inflight_htlcs: &InFlightHtlcs + ) -> Result { + let random_seed_bytes = { + let mut locked_random_seed_bytes = self.random_seed_bytes.lock().unwrap(); + *locked_random_seed_bytes = Sha256::hash(&*locked_random_seed_bytes).into_inner(); + *locked_random_seed_bytes + }; + + find_route( + payer, params, &self.network_graph, first_hops, &*self.logger, + &ScorerAccountingForInFlightHtlcs::new(self.scorer.lock(), inflight_htlcs), + &random_seed_bytes + ) + } + + fn notify_payment_path_failed(&self, path: &[&RouteHop], short_channel_id: u64) { + self.scorer.lock().payment_path_failed(path, short_channel_id); + } + + fn notify_payment_path_successful(&self, path: &[&RouteHop]) { + self.scorer.lock().payment_path_successful(path); + } + + fn notify_payment_probe_successful(&self, path: &[&RouteHop]) { + self.scorer.lock().probe_successful(path); + } + + fn notify_payment_probe_failed(&self, path: &[&RouteHop], short_channel_id: u64) { + self.scorer.lock().probe_failed(path, short_channel_id); + } +} + /// 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 + first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: &InFlightHtlcs ) -> Result; /// Finds a [`Route`] between `payer` and `payee` for a payment with the given values. Includes /// `PaymentHash` and `PaymentId` to be able to correlate the request with a specific payment. fn find_route_with_id( &self, payer: &PublicKey, route_params: &RouteParameters, - first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: InFlightHtlcs, + first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: &InFlightHtlcs, _payment_hash: PaymentHash, _payment_id: PaymentId ) -> Result { self.find_route(payer, route_params, first_hops, inflight_htlcs) @@ -63,14 +126,14 @@ pub trait Router { /// /// [`Score`]: crate::routing::scoring::Score pub struct ScorerAccountingForInFlightHtlcs<'a, S: Score> { - scorer: &'a mut S, + scorer: S, // Maps a channel's short channel id and its direction to the liquidity used up. - inflight_htlcs: InFlightHtlcs, + inflight_htlcs: &'a InFlightHtlcs, } impl<'a, S: Score> ScorerAccountingForInFlightHtlcs<'a, S> { /// Initialize a new `ScorerAccountingForInFlightHtlcs`. - pub fn new(scorer: &'a mut S, inflight_htlcs: InFlightHtlcs) -> Self { + pub fn new(scorer: S, inflight_htlcs: &'a InFlightHtlcs) -> Self { ScorerAccountingForInFlightHtlcs { scorer, inflight_htlcs @@ -79,7 +142,7 @@ impl<'a, S: Score> ScorerAccountingForInFlightHtlcs<'a, S> { } #[cfg(c_bindings)] -impl<'a, S:Score> Writeable for ScorerAccountingForInFlightHtlcs<'a, S> { +impl<'a, S: Score> Writeable for ScorerAccountingForInFlightHtlcs<'a, S> { fn write(&self, writer: &mut W) -> Result<(), io::Error> { self.scorer.write(writer) } } @@ -118,6 +181,7 @@ impl<'a, S: Score> Score for ScorerAccountingForInFlightHtlcs<'a, S> { /// A data structure for tracking in-flight HTLCs. May be used during pathfinding to account for /// in-use channel liquidity. +#[derive(Clone)] pub struct InFlightHtlcs( // 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 @@ -2075,7 +2139,7 @@ mod tests { use crate::routing::scoring::{ChannelUsage, Score, ProbabilisticScorer, ProbabilisticScoringParameters}; use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel}; use crate::chain::transaction::OutPoint; - use crate::chain::keysinterface::KeysInterface; + use crate::chain::keysinterface::EntropySource; use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures}; use crate::ln::msgs::{ErrorAction, LightningError, UnsignedChannelUpdate, MAX_VALUE_MSAT}; use crate::ln::channelmanager; @@ -2126,6 +2190,7 @@ mod tests { inbound_capacity_msat: 42, unspendable_punishment_reserve: None, confirmations_required: None, + confirmations: None, force_close_spend_delay: None, is_outbound: true, is_channel_ready: true, is_usable: true, is_public: true, @@ -5588,7 +5653,7 @@ mod benches { use bitcoin::hashes::Hash; use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; use crate::chain::transaction::OutPoint; - use crate::chain::keysinterface::{KeysManager,KeysInterface}; + use crate::chain::keysinterface::{EntropySource, KeysManager}; use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails}; use crate::ln::features::InvoiceFeatures; use crate::routing::gossip::NetworkGraph; @@ -5640,6 +5705,7 @@ mod benches { inbound_capacity_msat: 0, unspendable_punishment_reserve: None, confirmations_required: None, + confirmations: None, force_close_spend_delay: None, is_outbound: true, is_channel_ready: true,