Merge pull request #2177 from TheBlueMatt/2023-04-test-function-generics
[rust-lightning] / lightning / src / routing / gossip.rs
index ae2378c38242b82fc467f1bc9322ca588ec75cc4..59268b840cd4c411b7a1545905bf17a4b6a24be0 100644 (file)
@@ -16,11 +16,13 @@ use bitcoin::secp256k1;
 
 use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hashes::Hash;
+use bitcoin::hashes::hex::FromHex;
 use bitcoin::hash_types::BlockHash;
 
 use bitcoin::network::constants::Network;
 use bitcoin::blockdata::constants::genesis_block;
 
+use crate::events::{MessageSendEvent, MessageSendEventsProvider};
 use crate::ln::features::{ChannelFeatures, NodeFeatures, InitFeatures};
 use crate::ln::msgs::{DecodeError, ErrorAction, Init, LightningError, RoutingMessageHandler, NetAddress, MAX_VALUE_MSAT};
 use crate::ln::msgs::{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, GossipTimestampFilter};
@@ -29,7 +31,6 @@ use crate::ln::msgs;
 use crate::routing::utxo::{self, UtxoLookup};
 use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, MaybeReadable};
 use crate::util::logger::{Logger, Level};
-use crate::util::events::{MessageSendEvent, MessageSendEventsProvider};
 use crate::util::scid_utils::{block_from_scid, scid_from_parts, MAX_SCID_BLOCK};
 use crate::util::string::PrintableString;
 use crate::util::indexed_map::{IndexedMap, Entry as IndexedMapEntry};
@@ -38,11 +39,13 @@ use crate::io;
 use crate::io_extras::{copy, sink};
 use crate::prelude::*;
 use core::{cmp, fmt};
+use core::convert::TryFrom;
 use crate::sync::{RwLock, RwLockReadGuard};
 #[cfg(feature = "std")]
 use core::sync::atomic::{AtomicUsize, Ordering};
 use crate::sync::Mutex;
 use core::ops::{Bound, Deref};
+use core::str::FromStr;
 
 #[cfg(feature = "std")]
 use std::time::{SystemTime, UNIX_EPOCH};
@@ -76,6 +79,11 @@ impl NodeId {
        pub fn as_slice(&self) -> &[u8] {
                &self.0
        }
+
+       /// Get the public key from this NodeId
+       pub fn as_pubkey(&self) -> Result<PublicKey, secp256k1::Error> {
+               PublicKey::from_slice(&self.0)
+       }
 }
 
 impl fmt::Debug for NodeId {
@@ -130,6 +138,29 @@ impl Readable for NodeId {
        }
 }
 
+impl From<PublicKey> for NodeId {
+       fn from(pubkey: PublicKey) -> Self {
+               Self::from_pubkey(&pubkey)
+       }
+}
+
+impl TryFrom<NodeId> for PublicKey {
+       type Error = secp256k1::Error;
+
+       fn try_from(node_id: NodeId) -> Result<Self, Self::Error> {
+               node_id.as_pubkey()
+       }
+}
+
+impl FromStr for NodeId {
+       type Err = bitcoin::hashes::hex::Error;
+
+       fn from_str(s: &str) -> Result<Self, Self::Err> {
+               let data: [u8; PUBLIC_KEY_SIZE] = FromHex::from_hex(s)?;
+               Ok(NodeId(data))
+       }
+}
+
 /// Represents the network as nodes and channels between them
 pub struct NetworkGraph<L: Deref> where L::Target: Logger {
        secp_ctx: Secp256k1<secp256k1::VerifyOnly>,
@@ -234,7 +265,7 @@ impl<G: Deref<Target=NetworkGraph<L>>, U: Deref, L: Deref> P2PGossipSync<G, U, L
 where U::Target: UtxoLookup, L::Target: Logger
 {
        /// Creates a new tracker of the actual state of the network of channels and nodes,
-       /// assuming an existing Network Graph.
+       /// assuming an existing [`NetworkGraph`].
        /// UTXO lookup is used to make sure announced channels exist on-chain, channel data is
        /// correct, and the announcement is signed with channel owners' keys.
        pub fn new(network_graph: G, utxo_lookup: Option<U>, logger: L) -> Self {
@@ -258,7 +289,7 @@ where U::Target: UtxoLookup, L::Target: Logger
        /// Gets a reference to the underlying [`NetworkGraph`] which was provided in
        /// [`P2PGossipSync::new`].
        ///
-       /// (C-not exported) as bindings don't support a reference-to-a-reference yet
+       /// This is not exported to bindings users as bindings don't support a reference-to-a-reference yet
        pub fn network_graph(&self) -> &G {
                &self.network_graph
        }
@@ -310,7 +341,7 @@ where U::Target: UtxoLookup, L::Target: Logger
 impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
        /// Handles any network updates originating from [`Event`]s.
        ///
-       /// [`Event`]: crate::util::events::Event
+       /// [`Event`]: crate::events::Event
        pub fn handle_network_update(&self, network_update: &NetworkUpdate) {
                match *network_update {
                        NetworkUpdate::ChannelUpdateMessage { ref msg } => {
@@ -432,14 +463,20 @@ where U::Target: UtxoLookup, L::Target: Logger
        }
 
        /// Initiates a stateless sync of routing gossip information with a peer
-       /// using gossip_queries. The default strategy used by this implementation
+       /// using [`gossip_queries`]. The default strategy used by this implementation
        /// is to sync the full block range with several peers.
        ///
-       /// We should expect one or more reply_channel_range messages in response
-       /// to our query_channel_range. Each reply will enqueue a query_scid message
+       /// We should expect one or more [`reply_channel_range`] messages in response
+       /// to our [`query_channel_range`]. Each reply will enqueue a [`query_scid`] message
        /// to request gossip messages for each channel. The sync is considered complete
-       /// when the final reply_scids_end message is received, though we are not
+       /// when the final [`reply_scids_end`] message is received, though we are not
        /// tracking this directly.
+       ///
+       /// [`gossip_queries`]: https://github.com/lightning/bolts/blob/master/07-routing-gossip.md#query-messages
+       /// [`reply_channel_range`]: msgs::ReplyChannelRange
+       /// [`query_channel_range`]: msgs::QueryChannelRange
+       /// [`query_scid`]: msgs::QueryShortChannelIds
+       /// [`reply_scids_end`]: msgs::ReplyShortChannelIdsEnd
        fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &Init, _inbound: bool) -> Result<(), ()> {
                // We will only perform a sync with peers that support gossip_queries.
                if !init_msg.features.supports_gossip_queries() {
@@ -1097,7 +1134,7 @@ impl Readable for NodeAnnouncementInfo {
 ///
 /// Since node aliases are provided by third parties, they are a potential avenue for injection
 /// attacks. Care must be taken when processing.
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub struct NodeAlias(pub [u8; 32]);
 
 impl fmt::Display for NodeAlias {
@@ -1390,7 +1427,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
                                        features: msg.features.clone(),
                                        last_update: msg.timestamp,
                                        rgb: msg.rgb,
-                                       alias: NodeAlias(msg.alias),
+                                       alias: msg.alias,
                                        announcement_message: if should_relay { full_msg.cloned() } else { None },
                                });
 
@@ -1906,7 +1943,7 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
 impl ReadOnlyNetworkGraph<'_> {
        /// Returns all known valid channels' short ids along with announced channel info.
        ///
-       /// (C-not exported) because we don't want to return lifetime'd references
+       /// This is not exported to bindings users because we don't want to return lifetime'd references
        pub fn channels(&self) -> &IndexedMap<u64, ChannelInfo> {
                &*self.channels
        }
@@ -1924,7 +1961,7 @@ impl ReadOnlyNetworkGraph<'_> {
 
        /// Returns all known nodes' public keys along with announced node info.
        ///
-       /// (C-not exported) because we don't want to return lifetime'd references
+       /// This is not exported to bindings users because we don't want to return lifetime'd references
        pub fn nodes(&self) -> &IndexedMap<NodeId, NodeInfo> {
                &*self.nodes
        }
@@ -1951,6 +1988,7 @@ impl ReadOnlyNetworkGraph<'_> {
 
 #[cfg(test)]
 pub(crate) mod tests {
+       use crate::events::{MessageSendEvent, MessageSendEventsProvider};
        use crate::ln::channelmanager;
        use crate::ln::chan_utils::make_funding_redeemscript;
        #[cfg(feature = "std")]
@@ -1963,7 +2001,6 @@ pub(crate) mod tests {
        use crate::util::config::UserConfig;
        use crate::util::test_utils;
        use crate::util::ser::{ReadableArgs, Readable, Writeable};
-       use crate::util::events::{MessageSendEvent, MessageSendEventsProvider};
        use crate::util::scid_utils::scid_from_parts;
 
        use crate::routing::gossip::REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS;
@@ -2023,7 +2060,7 @@ pub(crate) mod tests {
                        timestamp: 100,
                        node_id,
                        rgb: [0; 3],
-                       alias: [0; 32],
+                       alias: NodeAlias([0; 32]),
                        addresses: Vec::new(),
                        excess_address_data: Vec::new(),
                        excess_data: Vec::new(),