X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Frouter.rs;h=a3f7f1532f8b476b148f9089fe8b5cb9b136b644;hb=511d7e3f5fe5900178cc43320d21089826681581;hp=f1901d7c50188e7e2b4e8b49d11c4bb590b4b829;hpb=7002180261d495f15c12f9a341af1e7dbcac2990;p=rust-lightning diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index f1901d7c..a3f7f153 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -13,7 +13,7 @@ use bitcoin::secp256k1::{PublicKey, Secp256k1, self}; use crate::blinded_path::{BlindedHop, BlindedPath, Direction, IntroductionNode}; use crate::blinded_path::payment::{ForwardNode, ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs}; -use crate::ln::PaymentHash; +use crate::ln::types::PaymentHash; use crate::ln::channelmanager::{ChannelDetails, PaymentId, MIN_FINAL_CLTV_EXPIRY_DELTA}; use crate::ln::features::{BlindedHopFeatures, Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures}; use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT}; @@ -1144,11 +1144,11 @@ pub struct FirstHopCandidate<'a> { /// /// [`find_route`] validates this prior to constructing a [`CandidateRouteHop`]. /// - /// This is not exported to bindings users as lifetimes are not expressable in most languages. + /// This is not exported to bindings users as lifetimes are not expressible in most languages. pub details: &'a ChannelDetails, /// The node id of the payer, which is also the source side of this candidate route hop. /// - /// This is not exported to bindings users as lifetimes are not expressable in most languages. + /// This is not exported to bindings users as lifetimes are not expressible in most languages. pub payer_node_id: &'a NodeId, } @@ -1158,7 +1158,7 @@ pub struct PublicHopCandidate<'a> { /// Information about the channel, including potentially its capacity and /// direction-specific information. /// - /// This is not exported to bindings users as lifetimes are not expressable in most languages. + /// This is not exported to bindings users as lifetimes are not expressible in most languages. pub info: DirectedChannelInfo<'a>, /// The short channel ID of the channel, i.e. the identifier by which we refer to this /// channel. @@ -1170,11 +1170,11 @@ pub struct PublicHopCandidate<'a> { pub struct PrivateHopCandidate<'a> { /// Information about the private hop communicated via BOLT 11. /// - /// This is not exported to bindings users as lifetimes are not expressable in most languages. + /// This is not exported to bindings users as lifetimes are not expressible in most languages. pub hint: &'a RouteHintHop, /// Node id of the next hop in BOLT 11 route hint. /// - /// This is not exported to bindings users as lifetimes are not expressable in most languages. + /// This is not exported to bindings users as lifetimes are not expressible in most languages. pub target_node_id: &'a NodeId } @@ -1189,7 +1189,7 @@ pub struct BlindedPathCandidate<'a> { /// Information about the blinded path including the fee, HTLC amount limits, and /// cryptographic material required to build an HTLC through the given path. /// - /// This is not exported to bindings users as lifetimes are not expressable in most languages. + /// This is not exported to bindings users as lifetimes are not expressible in most languages. pub hint: &'a (BlindedPayInfo, BlindedPath), /// Index of the hint in the original list of blinded hints. /// @@ -1211,7 +1211,7 @@ pub struct OneHopBlindedPathCandidate<'a> { /// /// Note that the [`BlindedPayInfo`] is ignored here. /// - /// This is not exported to bindings users as lifetimes are not expressable in most languages. + /// This is not exported to bindings users as lifetimes are not expressible in most languages. pub hint: &'a (BlindedPayInfo, BlindedPath), /// Index of the hint in the original list of blinded hints. /// @@ -1874,6 +1874,9 @@ where L::Target: Logger { return Err(LightningError{err: "Cannot send a payment of 0 msat".to_owned(), action: ErrorAction::IgnoreError}); } + let introduction_node_id_cache = payment_params.payee.blinded_route_hints().iter() + .map(|(_, path)| path.public_introduction_node_id(network_graph)) + .collect::>(); match &payment_params.payee { Payee::Clear { route_hints, node_id, .. } => { for route in route_hints.iter() { @@ -1885,17 +1888,19 @@ where L::Target: Logger { } }, Payee::Blinded { route_hints, .. } => { - if route_hints.iter().all(|(_, path)| path.public_introduction_node_id(network_graph) == Some(&our_node_id)) { + if introduction_node_id_cache.iter().all(|introduction_node_id| *introduction_node_id == Some(&our_node_id)) { return Err(LightningError{err: "Cannot generate a route to blinded paths if we are the introduction node to all of them".to_owned(), action: ErrorAction::IgnoreError}); } - for (_, blinded_path) in route_hints.iter() { + for ((_, blinded_path), introduction_node_id) in route_hints.iter().zip(introduction_node_id_cache.iter()) { if blinded_path.blinded_hops.len() == 0 { return Err(LightningError{err: "0-hop blinded path provided".to_owned(), action: ErrorAction::IgnoreError}); - } else if blinded_path.public_introduction_node_id(network_graph) == Some(&our_node_id) { + } else if *introduction_node_id == Some(&our_node_id) { log_info!(logger, "Got blinded path with ourselves as the introduction node, ignoring"); } else if blinded_path.blinded_hops.len() == 1 && - route_hints.iter().any( |(_, p)| p.blinded_hops.len() == 1 - && p.public_introduction_node_id(network_graph) != blinded_path.public_introduction_node_id(network_graph)) + route_hints + .iter().zip(introduction_node_id_cache.iter()) + .filter(|((_, p), _)| p.blinded_hops.len() == 1) + .any(|(_, p_introduction_node_id)| p_introduction_node_id != introduction_node_id) { return Err(LightningError{err: format!("1-hop blinded paths must all have matching introduction node ids"), action: ErrorAction::IgnoreError}); } @@ -1984,10 +1989,11 @@ where L::Target: Logger { let max_total_routing_fee_msat = route_params.max_total_routing_fee_msat.unwrap_or(u64::max_value()); - log_trace!(logger, "Searching for a route from payer {} to {} {} MPP and {} first hops {}overriding the network graph with a fee limit of {} msat", + log_trace!(logger, "Searching for a route from payer {} to {} {} MPP and {} first hops {}overriding the network graph of {} nodes and {} channels with a fee limit of {} msat", our_node_pubkey, LoggedPayeePubkey(payment_params.payee.node_id()), if allow_mpp { "with" } else { "without" }, first_hops.map(|hops| hops.len()).unwrap_or(0), if first_hops.is_some() { "" } else { "not " }, + network_graph.nodes().len(), network_graph.channels().len(), max_total_routing_fee_msat); // Step (1). @@ -2540,7 +2546,7 @@ where L::Target: Logger { // Only add the hops in this route to our candidate set if either // we have a direct channel to the first hop or the first hop is // in the regular network graph. - let source_node_id = match hint.1.public_introduction_node_id(network_graph) { + let source_node_id = match introduction_node_id_cache[hint_idx] { Some(node_id) => node_id, None => match &hint.1.introduction_node { IntroductionNode::NodeId(pubkey) => { @@ -3286,7 +3292,7 @@ mod tests { 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; - use crate::ln::ChannelId; + use crate::ln::types::ChannelId; use crate::ln::features::{BlindedHopFeatures, ChannelFeatures, InitFeatures, NodeFeatures}; use crate::ln::msgs::{ErrorAction, LightningError, UnsignedChannelUpdate, MAX_VALUE_MSAT}; use crate::ln::channelmanager; @@ -8408,7 +8414,7 @@ pub(crate) mod bench_utils { use crate::chain::transaction::OutPoint; use crate::routing::scoring::ScoreUpdate; use crate::sign::KeysManager; - use crate::ln::ChannelId; + use crate::ln::types::ChannelId; use crate::ln::channelmanager::{self, ChannelCounterparty}; use crate::util::config::UserConfig; use crate::util::test_utils::TestLogger;