Make `CandidateRouteHop::PrivateHop::target_node_id` a reference
authorMatt Corallo <git@bluematt.me>
Wed, 6 Dec 2023 03:54:28 +0000 (03:54 +0000)
committerMatt Corallo <git@bluematt.me>
Fri, 8 Dec 2023 20:45:06 +0000 (20:45 +0000)
This avoids bloating `CandidateRouteHop` with a full 33-byte
node_id (and avoids repeated public key serialization when we do
multiple pathfinding passes).

lightning/src/routing/router.rs
lightning/src/util/test_utils.rs

index 52678c42c8eb337295492a0c7e54b630d2c5c423..7b1df46fb65854e448c70e21e4c23eda20e7a404 100644 (file)
@@ -1039,7 +1039,7 @@ pub enum CandidateRouteHop<'a> {
                /// Information about the private hop communicated via BOLT 11.
                hint: &'a RouteHintHop,
                /// Node id of the next hop in BOLT 11 route hint.
-               target_node_id: NodeId
+               target_node_id: &'a NodeId
        },
        /// A blinded path which starts with an introduction point and ultimately terminates with the
        /// payee.
@@ -1250,7 +1250,7 @@ impl<'a> CandidateRouteHop<'a> {
                match self {
                        CandidateRouteHop::FirstHop { details, .. } => Some(details.counterparty.node_id.into()),
                        CandidateRouteHop::PublicHop { info, .. } => Some(*info.target()),
-                       CandidateRouteHop::PrivateHop { target_node_id, .. } => Some(*target_node_id),
+                       CandidateRouteHop::PrivateHop { target_node_id, .. } => Some(**target_node_id),
                        CandidateRouteHop::Blinded { .. } => None,
                        CandidateRouteHop::OneHopBlinded { .. } => None,
                }
@@ -1795,6 +1795,20 @@ where L::Target: Logger {
                }
        }
 
+       let mut private_hop_key_cache = HashMap::with_capacity(
+               payment_params.payee.unblinded_route_hints().iter().map(|path| path.0.len()).sum()
+       );
+
+       // Because we store references to private hop node_ids in `dist`, below, we need them to exist
+       // (as `NodeId`, not `PublicKey`) for the lifetime of `dist`. Thus, we calculate all the keys
+       // we'll need here and simply fetch them when routing.
+       private_hop_key_cache.insert(maybe_dummy_payee_pk, NodeId::from_pubkey(&maybe_dummy_payee_pk));
+       for route in payment_params.payee.unblinded_route_hints().iter() {
+               for hop in route.0.iter() {
+                       private_hop_key_cache.insert(hop.src_node_id, NodeId::from_pubkey(&hop.src_node_id));
+               }
+       }
+
        // The main heap containing all candidate next-hops sorted by their score (max(fee,
        // htlc_minimum)). Ideally this would be a heap which allowed cheap score reduction instead of
        // adding duplicate entries when we find a better path to a given node.
@@ -2353,8 +2367,7 @@ where L::Target: Logger {
                                let mut aggregate_path_contribution_msat = path_value_msat;
 
                                for (idx, (hop, prev_hop_id)) in hop_iter.zip(prev_hop_iter).enumerate() {
-                                       let source = NodeId::from_pubkey(&hop.src_node_id);
-                                       let target = NodeId::from_pubkey(&prev_hop_id);
+                                       let target = private_hop_key_cache.get(&prev_hop_id).unwrap();
 
                                        if let Some(first_channels) = first_hop_targets.get(&target) {
                                                if first_channels.iter().any(|d| d.outbound_scid_alias == Some(hop.short_channel_id)) {
index 1ae28b40e371d1122528305881f57f9e3a813daa..664deb9fa1566f6aa2628150458385673fd16cc8 100644 (file)
@@ -171,7 +171,7 @@ impl<'a> Router for TestRouter<'a> {
                                                        };
                                                        let candidate = CandidateRouteHop::PrivateHop {
                                                                hint: &route_hint,
-                                                               target_node_id: target_node_id,
+                                                               target_node_id: &target_node_id,
                                                        };
                                                        scorer.channel_penalty_msat(&candidate, usage, &());
                                                }