X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Frouter.rs;h=962080b0db47080d2d6fe90169b8276aef72b322;hb=3695b2aa13dcd271c9c4252cda3a0b9b79d3d879;hp=04fc9927bb7a9446437d12d8633cc99d39a13434;hpb=ef5be580f51d6756612fea710516c0297203f4dc;p=rust-lightning diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 04fc9927..962080b0 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -20,22 +20,22 @@ use crate::ln::features::{Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelF use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT}; use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice}; use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId, RoutingFees}; -use crate::routing::scoring::{ChannelUsage, LockableScore, Score}; +use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp}; use crate::util::ser::{Writeable, Readable, ReadableArgs, Writer}; use crate::util::logger::{Level, Logger}; use crate::util::chacha20::ChaCha20; use crate::io; use crate::prelude::*; -use crate::sync::{Mutex}; +use crate::sync::Mutex; use alloc::collections::BinaryHeap; use core::{cmp, fmt}; -use core::ops::{Deref, DerefMut}; +use core::ops::Deref; /// A [`Router`] implemented using [`find_route`]. -pub struct DefaultRouter>, L: Deref, S: Deref, SP: Sized, Sc: Score> where +pub struct DefaultRouter>, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> where L::Target: Logger, - S::Target: for <'a> LockableScore<'a, Score = Sc>, + S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, { network_graph: G, logger: L, @@ -44,9 +44,9 @@ pub struct DefaultRouter>, L: Deref, S: Deref, score_params: SP } -impl>, L: Deref, S: Deref, SP: Sized, Sc: Score> DefaultRouter where +impl>, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> DefaultRouter where L::Target: Logger, - S::Target: for <'a> LockableScore<'a, Score = Sc>, + S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, { /// Creates a new router. pub fn new(network_graph: G, logger: L, random_seed_bytes: [u8; 32], scorer: S, score_params: SP) -> Self { @@ -55,9 +55,9 @@ impl>, L: Deref, S: Deref, SP: Sized, Sc: Scor } } -impl< G: Deref>, L: Deref, S: Deref, SP: Sized, Sc: Score> Router for DefaultRouter where +impl< G: Deref>, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> Router for DefaultRouter where L::Target: Logger, - S::Target: for <'a> LockableScore<'a, Score = Sc>, + S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, { fn find_route( &self, @@ -73,7 +73,7 @@ impl< G: Deref>, L: Deref, S: Deref, SP: Sized, Sc: Sco }; find_route( payer, params, &self.network_graph, first_hops, &*self.logger, - &ScorerAccountingForInFlightHtlcs::new(self.scorer.lock().deref_mut(), &inflight_htlcs), + &ScorerAccountingForInFlightHtlcs::new(self.scorer.read_lock(), &inflight_htlcs), &self.score_params, &random_seed_bytes ) @@ -106,21 +106,20 @@ pub trait Router { } } -/// [`Score`] implementation that factors in in-flight HTLC liquidity. +/// [`ScoreLookUp`] implementation that factors in in-flight HTLC liquidity. /// -/// Useful for custom [`Router`] implementations to wrap their [`Score`] on-the-fly when calling +/// Useful for custom [`Router`] implementations to wrap their [`ScoreLookUp`] on-the-fly when calling /// [`find_route`]. /// -/// [`Score`]: crate::routing::scoring::Score -pub struct ScorerAccountingForInFlightHtlcs<'a, S: Score, SP: Sized> { - scorer: &'a mut S, +/// [`ScoreLookUp`]: crate::routing::scoring::ScoreLookUp +pub struct ScorerAccountingForInFlightHtlcs<'a, SP: Sized, Sc: 'a + ScoreLookUp, S: Deref> { + scorer: S, // Maps a channel's short channel id and its direction to the liquidity used up. inflight_htlcs: &'a InFlightHtlcs, } - -impl<'a, S: Score, SP: Sized> ScorerAccountingForInFlightHtlcs<'a, S, SP> { +impl<'a, SP: Sized, Sc: ScoreLookUp, S: Deref> ScorerAccountingForInFlightHtlcs<'a, SP, Sc, S> { /// Initialize a new `ScorerAccountingForInFlightHtlcs`. - pub fn new(scorer: &'a mut S, inflight_htlcs: &'a InFlightHtlcs) -> Self { + pub fn new(scorer: S, inflight_htlcs: &'a InFlightHtlcs) -> Self { ScorerAccountingForInFlightHtlcs { scorer, inflight_htlcs @@ -129,12 +128,12 @@ impl<'a, S: Score, SP: Sized> ScorerAccountingForInFlightHtlcs } #[cfg(c_bindings)] -impl<'a, S: Score, SP: Sized> Writeable for ScorerAccountingForInFlightHtlcs<'a, S, SP> { +impl<'a, SP: Sized, Sc: ScoreLookUp, S: Deref> Writeable for ScorerAccountingForInFlightHtlcs<'a, SP, Sc, S> { fn write(&self, writer: &mut W) -> Result<(), io::Error> { self.scorer.write(writer) } } -impl<'a, S: Score, SP: Sized> Score for ScorerAccountingForInFlightHtlcs<'a, S, SP> { - type ScoreParams = S::ScoreParams; +impl<'a, SP: Sized, Sc: 'a + ScoreLookUp, S: Deref> ScoreLookUp for ScorerAccountingForInFlightHtlcs<'a, SP, Sc, S> { + type ScoreParams = Sc::ScoreParams; fn channel_penalty_msat(&self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage, score_params: &Self::ScoreParams) -> u64 { if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity_msat( source, target, short_channel_id @@ -149,22 +148,6 @@ impl<'a, S: Score, SP: Sized> Score for ScorerAccountingForInF self.scorer.channel_penalty_msat(short_channel_id, source, target, usage, score_params) } } - - fn payment_path_failed(&mut self, path: &Path, short_channel_id: u64) { - self.scorer.payment_path_failed(path, short_channel_id) - } - - fn payment_path_successful(&mut self, path: &Path) { - self.scorer.payment_path_successful(path) - } - - fn probe_failed(&mut self, path: &Path, short_channel_id: u64) { - self.scorer.probe_failed(path, short_channel_id) - } - - fn probe_successful(&mut self, path: &Path) { - self.scorer.probe_successful(path) - } } /// A data structure for tracking in-flight HTLCs. May be used during pathfinding to account for @@ -425,7 +408,7 @@ impl Readable for Route { cmp::min(min_final_cltv_expiry_delta, hops.last().unwrap().cltv_expiry_delta); paths.push(Path { hops, blinded_tail: None }); } - _init_and_read_tlv_fields!(reader, { + _init_and_read_len_prefixed_tlv_fields!(reader, { (1, payment_params, (option: ReadableArgs, min_final_cltv_expiry_delta)), (2, blinded_tails, optional_vec), }); @@ -467,7 +450,7 @@ impl Writeable for RouteParameters { impl Readable for RouteParameters { fn read(reader: &mut R) -> Result { - _init_and_read_tlv_fields!(reader, { + _init_and_read_len_prefixed_tlv_fields!(reader, { (0, payment_params, (required: ReadableArgs, 0)), (2, final_value_msat, required), (4, final_cltv_delta, option), @@ -575,7 +558,7 @@ impl Writeable for PaymentParameters { impl ReadableArgs for PaymentParameters { fn read(reader: &mut R, default_final_cltv_expiry_delta: u32) -> Result { - _init_and_read_tlv_fields!(reader, { + _init_and_read_len_prefixed_tlv_fields!(reader, { (0, payee_pubkey, option), (1, max_total_cltv_expiry_delta, (default_value, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA)), (2, features, (option: ReadableArgs, payee_pubkey.is_some())), @@ -652,7 +635,7 @@ impl PaymentParameters { /// [`PaymentParameters::expiry_time`]. pub fn from_bolt12_invoice(invoice: &Bolt12Invoice) -> Self { Self::blinded(invoice.payment_paths().to_vec()) - .with_bolt12_features(invoice.features().clone()).unwrap() + .with_bolt12_features(invoice.invoice_features().clone()).unwrap() .with_expiry_time(invoice.created_at().as_secs().saturating_add(invoice.relative_expiry().as_secs())) } @@ -1410,7 +1393,7 @@ fn sort_first_hop_channels( /// [`ChannelManager::list_usable_channels`]: crate::ln::channelmanager::ChannelManager::list_usable_channels /// [`Event::PaymentPathFailed`]: crate::events::Event::PaymentPathFailed /// [`NetworkGraph`]: crate::routing::gossip::NetworkGraph -pub fn find_route( +pub fn find_route( our_node_pubkey: &PublicKey, route_params: &RouteParameters, network_graph: &NetworkGraph, first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S, score_params: &S::ScoreParams, random_seed_bytes: &[u8; 32] @@ -1424,7 +1407,7 @@ where L::Target: Logger, GL::Target: Logger { Ok(route) } -pub(crate) fn get_route( +pub(crate) fn get_route( our_node_pubkey: &PublicKey, payment_params: &PaymentParameters, network_graph: &ReadOnlyNetworkGraph, first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, logger: L, scorer: &S, score_params: &S::ScoreParams, _random_seed_bytes: &[u8; 32] @@ -2614,7 +2597,7 @@ fn build_route_from_hops_internal( hop_ids: [Option; MAX_PATH_LENGTH_ESTIMATE as usize], } - impl Score for HopScorer { + impl ScoreLookUp for HopScorer { type ScoreParams = (); fn channel_penalty_msat(&self, _short_channel_id: u64, source: &NodeId, target: &NodeId, _usage: ChannelUsage, _score_params: &Self::ScoreParams) -> u64 @@ -2632,14 +2615,6 @@ fn build_route_from_hops_internal( } u64::max_value() } - - fn payment_path_failed(&mut self, _path: &Path, _short_channel_id: u64) {} - - fn payment_path_successful(&mut self, _path: &Path) {} - - fn probe_failed(&mut self, _path: &Path, _short_channel_id: u64) {} - - fn probe_successful(&mut self, _path: &Path) {} } impl<'a> Writeable for HopScorer { @@ -2673,7 +2648,7 @@ mod tests { use crate::routing::router::{get_route, build_route_from_hops_internal, add_random_cltv_offset, default_node_features, BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE}; - use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, Score, ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters}; + use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, ScoreLookUp, ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters}; 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::sign::EntropySource; @@ -5720,16 +5695,11 @@ mod tests { impl Writeable for BadChannelScorer { fn write(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() } } - impl Score for BadChannelScorer { + impl ScoreLookUp for BadChannelScorer { type ScoreParams = (); fn channel_penalty_msat(&self, short_channel_id: u64, _: &NodeId, _: &NodeId, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 { if short_channel_id == self.short_channel_id { u64::max_value() } else { 0 } } - - fn payment_path_failed(&mut self, _path: &Path, _short_channel_id: u64) {} - fn payment_path_successful(&mut self, _path: &Path) {} - fn probe_failed(&mut self, _path: &Path, _short_channel_id: u64) {} - fn probe_successful(&mut self, _path: &Path) {} } struct BadNodeScorer { @@ -5741,16 +5711,11 @@ mod tests { fn write(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() } } - impl Score for BadNodeScorer { + impl ScoreLookUp for BadNodeScorer { type ScoreParams = (); fn channel_penalty_msat(&self, _: u64, _: &NodeId, target: &NodeId, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 { if *target == self.node_id { u64::max_value() } else { 0 } } - - fn payment_path_failed(&mut self, _path: &Path, _short_channel_id: u64) {} - fn payment_path_successful(&mut self, _path: &Path) {} - fn probe_failed(&mut self, _path: &Path, _short_channel_id: u64) {} - fn probe_successful(&mut self, _path: &Path) {} } #[test] @@ -6721,6 +6686,7 @@ pub(crate) mod bench_utils { use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; use crate::chain::transaction::OutPoint; + use crate::routing::scoring::ScoreUpdate; use crate::sign::{EntropySource, KeysManager}; use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails}; use crate::ln::features::Bolt11InvoiceFeatures; @@ -6813,7 +6779,7 @@ pub(crate) mod bench_utils { } } - pub(crate) fn generate_test_routes(graph: &NetworkGraph<&TestLogger>, scorer: &mut S, + pub(crate) fn generate_test_routes(graph: &NetworkGraph<&TestLogger>, scorer: &mut S, score_params: &S::ScoreParams, features: Bolt11InvoiceFeatures, mut seed: u64, starting_amount: u64, route_count: usize, ) -> Vec<(ChannelDetails, PaymentParameters, u64)> { @@ -6839,7 +6805,7 @@ pub(crate) mod bench_utils { let amt = starting_amount + seed % 1_000_000; let path_exists = get_route(&payer, ¶ms, &graph.read_only(), Some(&[&first_hop]), - amt, &TestLogger::new(), &scorer, score_params, &random_seed_bytes).is_ok(); + amt, &TestLogger::new(), scorer, score_params, &random_seed_bytes).is_ok(); if path_exists { // ...and seed the scorer with success and failure data... seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0; @@ -6853,7 +6819,7 @@ pub(crate) mod bench_utils { .with_bolt11_features(mpp_features).unwrap(); let route_res = get_route(&payer, ¶ms, &graph.read_only(), - Some(&[&first_hop]), score_amt, &TestLogger::new(), &scorer, + Some(&[&first_hop]), score_amt, &TestLogger::new(), scorer, score_params, &random_seed_bytes); if let Ok(route) = route_res { for path in route.paths { @@ -6882,7 +6848,7 @@ pub(crate) mod bench_utils { // requires a too-high CLTV delta. route_endpoints.retain(|(first_hop, params, amt)| { get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt, - &TestLogger::new(), &scorer, score_params, &random_seed_bytes).is_ok() + &TestLogger::new(), scorer, score_params, &random_seed_bytes).is_ok() }); route_endpoints.truncate(route_count); assert_eq!(route_endpoints.len(), route_count); @@ -6893,6 +6859,7 @@ pub(crate) mod bench_utils { #[cfg(ldk_bench)] pub mod benches { use super::*; + use crate::routing::scoring::{ScoreUpdate, ScoreLookUp}; use crate::sign::{EntropySource, KeysManager}; use crate::ln::channelmanager; use crate::ln::features::Bolt11InvoiceFeatures; @@ -6955,7 +6922,7 @@ pub mod benches { "generate_large_mpp_routes_with_probabilistic_scorer"); } - fn generate_routes( + fn generate_routes( bench: &mut Criterion, graph: &NetworkGraph<&TestLogger>, mut scorer: S, score_params: &S::ScoreParams, features: Bolt11InvoiceFeatures, starting_amount: u64, bench_name: &'static str,