Merge pull request #655 from lightning-signer/per-commitment
[rust-lightning] / lightning / src / routing / network_graph.rs
index 3168a1fd8503be206063bf23fa9abbd177180699..9c93b246f0762b72e2601151d5eff2f64ca7cdee 100644 (file)
@@ -16,13 +16,13 @@ use ln::msgs;
 use util::ser::{Writeable, Readable, Writer};
 use util::logger::Logger;
 
-use std::cmp;
+use std::{cmp, fmt};
 use std::sync::RwLock;
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::collections::BTreeMap;
 use std::collections::btree_map::Entry as BtreeEntry;
-use std;
 use std::ops::Deref;
+use bitcoin::hashes::hex::ToHex;
 
 /// Receives and validates network updates from peers,
 /// stores authentic and relevant data as a network graph.
@@ -59,10 +59,10 @@ impl<C: Deref, L: Deref> NetGraphMsgHandler<C, L> where C::Target: ChainWatchInt
 
        /// Creates a new tracker of the actual state of the network of channels and nodes,
        /// assuming an existing Network Graph.
-       pub fn from_net_graph(chain_monitor: C, logger: L, network_graph: RwLock<NetworkGraph>) -> Self {
+       pub fn from_net_graph(chain_monitor: C, logger: L, network_graph: NetworkGraph) -> Self {
                NetGraphMsgHandler {
                        secp_ctx: Secp256k1::verification_only(),
-                       network_graph,
+                       network_graph: RwLock::new(network_graph),
                        full_syncs_requested: AtomicUsize::new(0),
                        chain_monitor,
                        logger,
@@ -75,7 +75,7 @@ macro_rules! secp_verify_sig {
        ( $secp_ctx: expr, $msg: expr, $sig: expr, $pubkey: expr ) => {
                match $secp_ctx.verify($msg, $sig, $pubkey) {
                        Ok(_) => {},
-                       Err(_) => return Err(LightningError{err: "Invalid signature from remote node", action: ErrorAction::IgnoreError}),
+                       Err(_) => return Err(LightningError{err: "Invalid signature from remote node".to_owned(), action: ErrorAction::IgnoreError}),
                }
        };
 }
@@ -87,7 +87,7 @@ impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for N
 
        fn handle_channel_announcement(&self, msg: &msgs::ChannelAnnouncement) -> Result<bool, LightningError> {
                if msg.contents.node_id_1 == msg.contents.node_id_2 || msg.contents.bitcoin_key_1 == msg.contents.bitcoin_key_2 {
-                       return Err(LightningError{err: "Channel announcement node had a channel with itself", action: ErrorAction::IgnoreError});
+                       return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError});
                }
 
                let checked_utxo = match self.chain_monitor.get_chain_utxo(msg.contents.chain_hash, msg.contents.short_channel_id) {
@@ -98,7 +98,7 @@ impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for N
                                                                    .push_opcode(opcodes::all::OP_PUSHNUM_2)
                                                                    .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh();
                                if script_pubkey != expected_script {
-                                       return Err(LightningError{err: "Channel announcement keys didn't match on-chain script", action: ErrorAction::IgnoreError});
+                                       return Err(LightningError{err: format!("Channel announcement key ({}) didn't match on-chain script ({})", script_pubkey.to_hex(), expected_script.to_hex()), action: ErrorAction::IgnoreError});
                                }
                                //TODO: Check if value is worth storing, use it to inform routing, and compare it
                                //to the new HTLC max field in channel_update
@@ -109,10 +109,10 @@ impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for N
                                false
                        },
                        Err(ChainError::NotWatched) => {
-                               return Err(LightningError{err: "Channel announced on an unknown chain", action: ErrorAction::IgnoreError});
+                               return Err(LightningError{err: format!("Channel announced on an unknown chain ({})", msg.contents.chain_hash.encode().to_hex()), action: ErrorAction::IgnoreError});
                        },
                        Err(ChainError::UnknownTx) => {
-                               return Err(LightningError{err: "Channel announced without corresponding UTXO entry", action: ErrorAction::IgnoreError});
+                               return Err(LightningError{err: "Channel announced without corresponding UTXO entry".to_owned(), action: ErrorAction::IgnoreError});
                        },
                };
                let result = self.network_graph.write().unwrap().update_channel_from_announcement(msg, checked_utxo, Some(&self.secp_ctx));
@@ -125,11 +125,11 @@ impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for N
                        &msgs::HTLCFailChannelUpdate::ChannelUpdateMessage { ref msg } => {
                                let _ = self.network_graph.write().unwrap().update_channel(msg, Some(&self.secp_ctx));
                        },
-                       &msgs::HTLCFailChannelUpdate::ChannelClosed { ref short_channel_id, ref is_permanent } => {
-                               self.network_graph.write().unwrap().close_channel_from_update(short_channel_id, &is_permanent);
+                       &msgs::HTLCFailChannelUpdate::ChannelClosed { short_channel_id, is_permanent } => {
+                               self.network_graph.write().unwrap().close_channel_from_update(short_channel_id, is_permanent);
                        },
-                       &msgs::HTLCFailChannelUpdate::NodeFailure { ref node_id, ref is_permanent } => {
-                               self.network_graph.write().unwrap().fail_node(node_id, &is_permanent);
+                       &msgs::HTLCFailChannelUpdate::NodeFailure { ref node_id, is_permanent } => {
+                               self.network_graph.write().unwrap().fail_node(node_id, is_permanent);
                        },
                }
        }
@@ -224,8 +224,8 @@ pub struct DirectionalChannelInfo {
        pub last_update_message: Option<msgs::ChannelUpdate>,
 }
 
-impl std::fmt::Display for DirectionalChannelInfo {
-       fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+impl fmt::Display for DirectionalChannelInfo {
+       fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
                write!(f, "last_update {}, enabled {}, cltv_expiry_delta {}, htlc_minimum_msat {}, fees {:?}", self.last_update, self.enabled, self.cltv_expiry_delta, self.htlc_minimum_msat, self.fees)?;
                Ok(())
        }
@@ -261,8 +261,8 @@ pub struct ChannelInfo {
        pub announcement_message: Option<msgs::ChannelAnnouncement>,
 }
 
-impl std::fmt::Display for ChannelInfo {
-       fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+impl fmt::Display for ChannelInfo {
+       fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
                write!(f, "features: {}, node_one: {}, one_to_two: {:?}, node_two: {}, two_to_one: {:?}",
                   log_bytes!(self.features.encode()), log_pubkey!(self.node_one), self.one_to_two, log_pubkey!(self.node_two), self.two_to_one)?;
                Ok(())
@@ -389,8 +389,8 @@ pub struct NodeInfo {
        pub announcement_info: Option<NodeAnnouncementInfo>
 }
 
-impl std::fmt::Display for NodeInfo {
-       fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+impl fmt::Display for NodeInfo {
+       fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
                write!(f, "lowest_inbound_channel_fees: {:?}, channels: {:?}, announcement_info: {:?}",
                   self.lowest_inbound_channel_fees, &self.channels[..], self.announcement_info)?;
                Ok(())
@@ -474,8 +474,8 @@ impl Readable for NetworkGraph {
        }
 }
 
-impl std::fmt::Display for NetworkGraph {
-       fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+impl fmt::Display for NetworkGraph {
+       fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
                write!(f, "Network map\n[Channels]\n")?;
                for (key, val) in self.channels.iter() {
                        write!(f, " {}: {}\n", key, val)?;
@@ -506,6 +506,14 @@ impl NetworkGraph {
                None
        }
 
+       /// Creates a new, empty, network graph.
+       pub fn new() -> NetworkGraph {
+               Self {
+                       channels: BTreeMap::new(),
+                       nodes: BTreeMap::new(),
+               }
+       }
+
        /// For an already known node (from channel announcements), update its stored properties from a given node announcement
        /// Announcement signatures are checked here only if Secp256k1 object is provided.
        fn update_node_from_announcement(&mut self, msg: &msgs::NodeAnnouncement, secp_ctx: Option<&Secp256k1<secp256k1::VerifyOnly>>) -> Result<bool, LightningError> {
@@ -515,11 +523,11 @@ impl NetworkGraph {
                }
 
                match self.nodes.get_mut(&msg.contents.node_id) {
-                       None => Err(LightningError{err: "No existing channels for node_announcement", action: ErrorAction::IgnoreError}),
+                       None => Err(LightningError{err: "No existing channels for node_announcement".to_owned(), action: ErrorAction::IgnoreError}),
                        Some(node) => {
                                if let Some(node_info) = node.announcement_info.as_ref() {
                                        if node_info.last_update  >= msg.contents.timestamp {
-                                               return Err(LightningError{err: "Update older than last processed update", action: ErrorAction::IgnoreError});
+                                               return Err(LightningError{err: "Update older than last processed update".to_owned(), action: ErrorAction::IgnoreError});
                                        }
                                }
 
@@ -581,7 +589,7 @@ impl NetworkGraph {
                                        Self::remove_channel_in_nodes(&mut self.nodes, &entry.get(), msg.contents.short_channel_id);
                                        *entry.get_mut() = chan_info;
                                } else {
-                                       return Err(LightningError{err: "Already have knowledge of channel", action: ErrorAction::IgnoreError})
+                                       return Err(LightningError{err: "Already have knowledge of channel".to_owned(), action: ErrorAction::IgnoreError})
                                }
                        },
                        BtreeEntry::Vacant(entry) => {
@@ -616,10 +624,10 @@ impl NetworkGraph {
        /// If permanent, removes a channel from the local storage.
        /// May cause the removal of nodes too, if this was their last channel.
        /// If not permanent, makes channels unavailable for routing.
-       pub fn close_channel_from_update(&mut self, short_channel_id: &u64, is_permanent: &bool) {
-               if *is_permanent {
-                       if let Some(chan) = self.channels.remove(short_channel_id) {
-                               Self::remove_channel_in_nodes(&mut self.nodes, &chan, *short_channel_id);
+       pub fn close_channel_from_update(&mut self, short_channel_id: u64, is_permanent: bool) {
+               if is_permanent {
+                       if let Some(chan) = self.channels.remove(&short_channel_id) {
+                               Self::remove_channel_in_nodes(&mut self.nodes, &chan, short_channel_id);
                        }
                } else {
                        if let Some(chan) = self.channels.get_mut(&short_channel_id) {
@@ -633,8 +641,8 @@ impl NetworkGraph {
                }
        }
 
-       fn fail_node(&mut self, _node_id: &PublicKey, is_permanent: &bool) {
-               if *is_permanent {
+       fn fail_node(&mut self, _node_id: &PublicKey, is_permanent: bool) {
+               if is_permanent {
                        // TODO: Wholly remove the node
                } else {
                        // TODO: downgrade the node
@@ -649,13 +657,13 @@ impl NetworkGraph {
                let chan_was_enabled;
 
                match self.channels.get_mut(&msg.contents.short_channel_id) {
-                       None => return Err(LightningError{err: "Couldn't find channel for update", action: ErrorAction::IgnoreError}),
+                       None => return Err(LightningError{err: "Couldn't find channel for update".to_owned(), action: ErrorAction::IgnoreError}),
                        Some(channel) => {
                                macro_rules! maybe_update_channel_info {
                                        ( $target: expr, $src_node: expr) => {
                                                if let Some(existing_chan_info) = $target.as_ref() {
                                                        if existing_chan_info.last_update >= msg.contents.timestamp {
-                                                               return Err(LightningError{err: "Update older than last processed update", action: ErrorAction::IgnoreError});
+                                                               return Err(LightningError{err: "Update older than last processed update".to_owned(), action: ErrorAction::IgnoreError});
                                                        }
                                                        chan_was_enabled = existing_chan_info.enabled;
                                                } else {