Add BlindedPath::introduction_node_id method
authorJeffrey Czyz <jkczyz@gmail.com>
Wed, 20 Mar 2024 21:42:30 +0000 (16:42 -0500)
committerJeffrey Czyz <jkczyz@gmail.com>
Thu, 11 Apr 2024 00:11:20 +0000 (19:11 -0500)
Blinded paths use a pubkey to identify the introduction node, but it
will soon allow using a directed short channel id instead. Add an
introduction_node_id method to BlindedPath to facilitate lookup in the
latter case.

lightning/src/blinded_path/mod.rs
lightning/src/routing/router.rs

index e70f310f5e1d8b00875ff58e069f432bd69526cf..5d199269520e16c9c79464a01a86a2d55b098d8b 100644 (file)
@@ -17,6 +17,7 @@ use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
 
 use crate::ln::msgs::DecodeError;
 use crate::offers::invoice::BlindedPayInfo;
+use crate::routing::gossip::{NodeId, ReadOnlyNetworkGraph};
 use crate::sign::EntropySource;
 use crate::util::ser::{Readable, Writeable, Writer};
 
@@ -125,6 +126,14 @@ impl BlindedPath {
                        ).map_err(|_| ())?,
                }))
        }
+
+       /// Returns the introduction [`NodeId`] of the blinded path.
+       pub fn public_introduction_node_id<'a>(
+               &self, network_graph: &'a ReadOnlyNetworkGraph
+       ) -> Option<&'a NodeId> {
+               let node_id = NodeId::from_pubkey(&self.introduction_node_id);
+               network_graph.nodes().get_key_value(&node_id).map(|(key, _)| key)
+       }
 }
 
 impl Writeable for BlindedPath {
index e8276712ee89504e002b619aa70544a147467840..b01d853be334cf3635d7f116ba0b878d8648ac43 100644 (file)
@@ -1863,17 +1863,17 @@ where L::Target: Logger {
                        }
                },
                Payee::Blinded { route_hints, .. } => {
-                       if route_hints.iter().all(|(_, path)| &path.introduction_node_id == our_node_pubkey) {
+                       if route_hints.iter().all(|(_, path)| path.public_introduction_node_id(network_graph) == 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() {
                                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.introduction_node_id == our_node_pubkey {
+                               } else if blinded_path.public_introduction_node_id(network_graph) == 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.introduction_node_id != blinded_path.introduction_node_id)
+                                               && p.public_introduction_node_id(network_graph) != blinded_path.public_introduction_node_id(network_graph))
                                {
                                        return Err(LightningError{err: format!("1-hop blinded paths must all have matching introduction node ids"), action: ErrorAction::IgnoreError});
                                }
@@ -5301,10 +5301,15 @@ mod tests {
                                if let Some(bt) = &path.blinded_tail {
                                        assert_eq!(path.hops.len() + if bt.hops.len() == 1 { 0 } else { 1 }, 2);
                                        if bt.hops.len() > 1 {
-                                               assert_eq!(path.hops.last().unwrap().pubkey,
+                                               let network_graph = network_graph.read_only();
+                                               assert_eq!(
+                                                       NodeId::from_pubkey(&path.hops.last().unwrap().pubkey),
                                                        payment_params.payee.blinded_route_hints().iter()
                                                                .find(|(p, _)| p.htlc_maximum_msat == path.final_value_msat())
-                                                               .map(|(_, p)| p.introduction_node_id).unwrap());
+                                                               .and_then(|(_, p)| p.public_introduction_node_id(&network_graph))
+                                                               .copied()
+                                                               .unwrap()
+                                               );
                                        } else {
                                                assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
                                        }
@@ -7432,7 +7437,10 @@ mod tests {
                assert_eq!(tail.final_value_msat, 1001);
 
                let final_hop = route.paths[0].hops.last().unwrap();
-               assert_eq!(final_hop.pubkey, blinded_path.introduction_node_id);
+               assert_eq!(
+                       NodeId::from_pubkey(&final_hop.pubkey),
+                       *blinded_path.public_introduction_node_id(&network_graph).unwrap()
+               );
                if tail.hops.len() > 1 {
                        assert_eq!(final_hop.fee_msat,
                                blinded_payinfo.fee_base_msat as u64 + blinded_payinfo.fee_proportional_millionths as u64 * tail.final_value_msat / 1000000);