//! 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<G: Deref<Target = NetworkGraph<L>>, 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<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref> DefaultRouter<G, L, S> 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<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref> Router for DefaultRouter<G, L, S> 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<Route, LightningError> {
+ 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<Route, LightningError>;
/// 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<Route, LightningError> {
self.find_route(payer, route_params, first_hops, inflight_htlcs)
///
/// [`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
}
#[cfg(c_bindings)]
-impl<'a, S:Score> Writeable for ScorerAccountingForInFlightHtlcs<'a, S> {
+impl<'a, S: Score> Writeable for ScorerAccountingForInFlightHtlcs<'a, S> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> { self.scorer.write(writer) }
}
/// 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
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;
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,
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;
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,