Use APIError::ChannelUnavailable a bit more for consistency
[rust-lightning] / src / ln / router.rs
index 1ca55fa260004c25e2cfafbe3856f1923257220a..4a55df88c6f90fd30d309e506377d819a7720a02 100644 (file)
@@ -1,12 +1,21 @@
+//! The top-level routing/network map tracking logic lives here.
+//!
+//! You probably want to create a Router and use that as your RoutingMessageHandler and then
+//! interrogate it to get routes for your own payments.
+
 use secp256k1::key::PublicKey;
 use secp256k1::{Secp256k1,Message};
 use secp256k1;
 
 use bitcoin::util::hash::Sha256dHash;
+use bitcoin::blockdata::script::Builder;
+use bitcoin::blockdata::opcodes;
 
+use chain::chaininterface::{ChainError, ChainWatchInterface};
 use ln::channelmanager;
-use ln::msgs::{ErrorAction,HandleError,RoutingMessageHandler,MsgEncodable,NetAddress,GlobalFeatures};
+use ln::msgs::{ErrorAction,HandleError,RoutingMessageHandler,NetAddress,GlobalFeatures};
 use ln::msgs;
+use util::ser::Writeable;
 use util::logger::Logger;
 
 use std::cmp;
@@ -18,6 +27,7 @@ use std;
 /// A hop in a route
 #[derive(Clone)]
 pub struct RouteHop {
+       /// The node_id of the node at this hop.
        pub pubkey: PublicKey,
        /// The channel that should be used from the previous hop to reach this node.
        pub short_channel_id: u64,
@@ -99,7 +109,21 @@ struct NetworkMap {
        our_node_id: PublicKey,
        nodes: HashMap<PublicKey, NodeInfo>,
 }
-
+struct MutNetworkMap<'a> {
+       #[cfg(feature = "non_bitcoin_chain_hash_routing")]
+       channels: &'a mut HashMap<(u64, Sha256dHash), ChannelInfo>,
+       #[cfg(not(feature = "non_bitcoin_chain_hash_routing"))]
+       channels: &'a mut HashMap<u64, ChannelInfo>,
+       nodes: &'a mut HashMap<PublicKey, NodeInfo>,
+}
+impl NetworkMap {
+       fn borrow_parts(&mut self) -> MutNetworkMap {
+               MutNetworkMap {
+                       channels: &mut self.channels,
+                       nodes: &mut self.nodes,
+               }
+       }
+}
 impl std::fmt::Display for NetworkMap {
        fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
                write!(f, "Node id {} network map\n[Channels]\n", log_pubkey!(self.our_node_id))?;
@@ -142,11 +166,18 @@ impl NetworkMap {
 
 /// A channel descriptor which provides a last-hop route to get_route
 pub struct RouteHint {
+       /// The node_id of the non-target end of the route
        pub src_node_id: PublicKey,
+       /// The short_channel_id of this channel
        pub short_channel_id: u64,
+       /// The static msat-denominated fee which must be paid to use this channel
        pub fee_base_msat: u32,
+       /// The dynamic proportional fee which must be paid to use this channel, denominated in
+       /// millionths of the value being forwarded to the next hop.
        pub fee_proportional_millionths: u32,
+       /// The difference in CLTV values between this node and the next node.
        pub cltv_expiry_delta: u16,
+       /// The minimum value, in msat, which must be relayed to the next hop.
        pub htlc_minimum_msat: u64,
 }
 
@@ -155,6 +186,7 @@ pub struct RouteHint {
 pub struct Router {
        secp_ctx: Secp256k1<secp256k1::VerifyOnly>,
        network_map: RwLock<NetworkMap>,
+       chain_monitor: Arc<ChainWatchInterface>,
        logger: Arc<Logger>,
 }
 
@@ -168,10 +200,14 @@ macro_rules! secp_verify_sig {
 }
 
 impl RoutingMessageHandler for Router {
-       fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<(), HandleError> {
+       fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<bool, HandleError> {
                let msg_hash = Message::from_slice(&Sha256dHash::from_data(&msg.contents.encode()[..])[..]).unwrap();
                secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.signature, &msg.contents.node_id);
 
+               if msg.contents.features.requires_unknown_bits() {
+                       panic!("Unknown-required-features NodeAnnouncements should never deserialize!");
+               }
+
                let mut network = self.network_map.write().unwrap();
                match network.nodes.get_mut(&msg.contents.node_id) {
                        None => Err(HandleError{err: "No existing channels for node_announcement", action: Some(ErrorAction::IgnoreError)}),
@@ -185,56 +221,98 @@ impl RoutingMessageHandler for Router {
                                node.rgb = msg.contents.rgb;
                                node.alias = msg.contents.alias;
                                node.addresses = msg.contents.addresses.clone();
-                               Ok(())
+                               Ok(msg.contents.excess_data.is_empty() && msg.contents.excess_address_data.is_empty() && !msg.contents.features.supports_unknown_bits())
                        }
                }
        }
 
        fn handle_channel_announcement(&self, msg: &msgs::ChannelAnnouncement) -> Result<bool, HandleError> {
+               if msg.contents.node_id_1 == msg.contents.node_id_2 || msg.contents.bitcoin_key_1 == msg.contents.bitcoin_key_2 {
+                       return Err(HandleError{err: "Channel announcement node had a channel with itself", action: Some(ErrorAction::IgnoreError)});
+               }
+
                let msg_hash = Message::from_slice(&Sha256dHash::from_data(&msg.contents.encode()[..])[..]).unwrap();
                secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_1, &msg.contents.node_id_1);
                secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_2, &msg.contents.node_id_2);
                secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1);
                secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2);
 
-               //TODO: Call blockchain thing to ask if the short_channel_id is valid
-               //TODO: Only allow bitcoin chain_hash
-
                if msg.contents.features.requires_unknown_bits() {
-                       return Err(HandleError{err: "Channel announcement required unknown feature flags", action: None});
+                       panic!("Unknown-required-features ChannelAnnouncements should never deserialize!");
                }
 
-               let mut network = self.network_map.write().unwrap();
+               let checked_utxo = match self.chain_monitor.get_chain_utxo(msg.contents.chain_hash, msg.contents.short_channel_id) {
+                       Ok((script_pubkey, _value)) => {
+                               let expected_script = Builder::new().push_opcode(opcodes::All::OP_PUSHNUM_2)
+                                                                   .push_slice(&msg.contents.bitcoin_key_1.serialize())
+                                                                   .push_slice(&msg.contents.bitcoin_key_2.serialize())
+                                                                   .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(HandleError{err: "Channel announcement keys didn't match on-chain script", action: Some(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
+                               true
+                       },
+                       Err(ChainError::NotSupported) => {
+                               // Tentatively accept, potentially exposing us to DoS attacks
+                               false
+                       },
+                       Err(ChainError::NotWatched) => {
+                               return Err(HandleError{err: "Channel announced on an unknown chain", action: Some(ErrorAction::IgnoreError)});
+                       },
+                       Err(ChainError::UnknownTx) => {
+                               return Err(HandleError{err: "Channel announced without corresponding UTXO entry", action: Some(ErrorAction::IgnoreError)});
+                       },
+               };
+
+               let mut network_lock = self.network_map.write().unwrap();
+               let network = network_lock.borrow_parts();
+
+               let chan_info = ChannelInfo {
+                               features: msg.contents.features.clone(),
+                               one_to_two: DirectionalChannelInfo {
+                                       src_node_id: msg.contents.node_id_1.clone(),
+                                       last_update: 0,
+                                       enabled: false,
+                                       cltv_expiry_delta: u16::max_value(),
+                                       htlc_minimum_msat: u64::max_value(),
+                                       fee_base_msat: u32::max_value(),
+                                       fee_proportional_millionths: u32::max_value(),
+                               },
+                               two_to_one: DirectionalChannelInfo {
+                                       src_node_id: msg.contents.node_id_2.clone(),
+                                       last_update: 0,
+                                       enabled: false,
+                                       cltv_expiry_delta: u16::max_value(),
+                                       htlc_minimum_msat: u64::max_value(),
+                                       fee_base_msat: u32::max_value(),
+                                       fee_proportional_millionths: u32::max_value(),
+                               }
+                       };
 
                match network.channels.entry(NetworkMap::get_key(msg.contents.short_channel_id, msg.contents.chain_hash)) {
-                       Entry::Occupied(_) => {
+                       Entry::Occupied(mut entry) => {
                                //TODO: because asking the blockchain if short_channel_id is valid is only optional
                                //in the blockchain API, we need to handle it smartly here, though its unclear
                                //exactly how...
-                               return Err(HandleError{err: "Already have knowledge of channel", action: Some(ErrorAction::IgnoreError)})
+                               if checked_utxo {
+                                       // Either our UTXO provider is busted, there was a reorg, or the UTXO provider
+                                       // only sometimes returns results. In any case remove the previous entry. Note
+                                       // that the spec expects us to "blacklist" the node_ids involved, but we can't
+                                       // do that because
+                                       // a) we don't *require* a UTXO provider that always returns results.
+                                       // b) we don't track UTXOs of channels we know about and remove them if they
+                                       //    get reorg'd out.
+                                       // c) it's unclear how to do so without exposing ourselves to massive DoS risk.
+                                       Self::remove_channel_in_nodes(network.nodes, &entry.get(), msg.contents.short_channel_id);
+                                       *entry.get_mut() = chan_info;
+                               } else {
+                                       return Err(HandleError{err: "Already have knowledge of channel", action: Some(ErrorAction::IgnoreError)})
+                               }
                        },
                        Entry::Vacant(entry) => {
-                               entry.insert(ChannelInfo {
-                                       features: msg.contents.features.clone(),
-                                       one_to_two: DirectionalChannelInfo {
-                                               src_node_id: msg.contents.node_id_1.clone(),
-                                               last_update: 0,
-                                               enabled: false,
-                                               cltv_expiry_delta: u16::max_value(),
-                                               htlc_minimum_msat: u64::max_value(),
-                                               fee_base_msat: u32::max_value(),
-                                               fee_proportional_millionths: u32::max_value(),
-                                       },
-                                       two_to_one: DirectionalChannelInfo {
-                                               src_node_id: msg.contents.node_id_2.clone(),
-                                               last_update: 0,
-                                               enabled: false,
-                                               cltv_expiry_delta: u16::max_value(),
-                                               htlc_minimum_msat: u64::max_value(),
-                                               fee_base_msat: u32::max_value(),
-                                               fee_proportional_millionths: u32::max_value(),
-                                       }
-                               });
+                               entry.insert(chan_info);
                        }
                };
 
@@ -263,7 +341,7 @@ impl RoutingMessageHandler for Router {
                add_channel_to_node!(msg.contents.node_id_1);
                add_channel_to_node!(msg.contents.node_id_2);
 
-               Ok(!msg.contents.features.supports_unknown_bits())
+               Ok(msg.contents.excess_data.is_empty() && !msg.contents.features.supports_unknown_bits())
        }
 
        fn handle_htlc_fail_channel_update(&self, update: &msgs::HTLCFailChannelUpdate) {
@@ -274,18 +352,13 @@ impl RoutingMessageHandler for Router {
                        &msgs::HTLCFailChannelUpdate::ChannelClosed { ref short_channel_id } => {
                                let mut network = self.network_map.write().unwrap();
                                if let Some(chan) = network.channels.remove(short_channel_id) {
-                                       network.nodes.get_mut(&chan.one_to_two.src_node_id).unwrap().channels.retain(|chan_id| {
-                                               chan_id != NetworkMap::get_short_id(chan_id)
-                                       });
-                                       network.nodes.get_mut(&chan.two_to_one.src_node_id).unwrap().channels.retain(|chan_id| {
-                                               chan_id != NetworkMap::get_short_id(chan_id)
-                                       });
+                                       Self::remove_channel_in_nodes(&mut network.nodes, &chan, *short_channel_id);
                                }
                        },
                }
        }
 
-       fn handle_channel_update(&self, msg: &msgs::ChannelUpdate) -> Result<(), HandleError> {
+       fn handle_channel_update(&self, msg: &msgs::ChannelUpdate) -> Result<bool, HandleError> {
                let mut network = self.network_map.write().unwrap();
                let dest_node_id;
                let chan_enabled = msg.contents.flags & (1 << 1) != (1 << 1);
@@ -351,7 +424,7 @@ impl RoutingMessageHandler for Router {
                        mut_node.lowest_inbound_channel_fee_proportional_millionths = lowest_inbound_channel_fee_proportional_millionths;
                }
 
-               Ok(())
+               Ok(msg.contents.excess_data.is_empty())
        }
 }
 
@@ -384,7 +457,8 @@ struct DummyDirectionalChannelInfo {
 }
 
 impl Router {
-       pub fn new(our_pubkey: PublicKey, logger: Arc<Logger>) -> Router {
+       /// Creates a new router with the given node_id to be used as the source for get_route()
+       pub fn new(our_pubkey: PublicKey, chain_monitor: Arc<ChainWatchInterface>, logger: Arc<Logger>) -> Router {
                let mut nodes = HashMap::new();
                nodes.insert(our_pubkey.clone(), NodeInfo {
                        channels: Vec::new(),
@@ -403,6 +477,7 @@ impl Router {
                                our_node_id: our_pubkey,
                                nodes: nodes,
                        }),
+                       chain_monitor,
                        logger,
                }
        }
@@ -429,14 +504,38 @@ impl Router {
                unimplemented!();
        }
 
+       fn remove_channel_in_nodes(nodes: &mut HashMap<PublicKey, NodeInfo>, chan: &ChannelInfo, short_channel_id: u64) {
+               macro_rules! remove_from_node {
+                       ($node_id: expr) => {
+                               if let Entry::Occupied(mut entry) = nodes.entry($node_id) {
+                                       entry.get_mut().channels.retain(|chan_id| {
+                                               short_channel_id != *NetworkMap::get_short_id(chan_id)
+                                       });
+                                       if entry.get().channels.is_empty() {
+                                               entry.remove_entry();
+                                       }
+                               } else {
+                                       panic!("Had channel that pointed to unknown node (ie inconsistent network map)!");
+                               }
+                       }
+               }
+               remove_from_node!(chan.one_to_two.src_node_id);
+               remove_from_node!(chan.two_to_one.src_node_id);
+       }
+
        /// Gets a route from us to the given target node.
+       ///
        /// Extra routing hops between known nodes and the target will be used if they are included in
        /// last_hops.
+       ///
        /// If some channels aren't announced, it may be useful to fill in a first_hops with the
        /// results from a local ChannelManager::list_usable_channels() call. If it is filled in, our
        /// (this Router's) view of our local channels will be ignored, and only those in first_hops
-       /// will be used. Panics if first_hops contains channels without short_channel_ids
+       /// will be used.
+       ///
+       /// Panics if first_hops contains channels without short_channel_ids
        /// (ChannelManager::list_usable_channels will never include such channels).
+       ///
        /// The fees on channels from us to next-hops are ignored (as they are assumed to all be
        /// equal), however the enabled/disabled bit on such channels as well as the htlc_minimum_msat
        /// *is* checked as they may change based on the receiving node.
@@ -628,6 +727,7 @@ impl Router {
 
 #[cfg(test)]
 mod tests {
+       use chain::chaininterface;
        use ln::channelmanager;
        use ln::router::{Router,NodeInfo,NetworkMap,ChannelInfo,DirectionalChannelInfo,RouteHint};
        use ln::msgs::GlobalFeatures;
@@ -635,6 +735,7 @@ mod tests {
        use util::logger::Logger;
 
        use bitcoin::util::hash::Sha256dHash;
+       use bitcoin::network::constants::Network;
 
        use hex;
 
@@ -648,7 +749,8 @@ mod tests {
                let secp_ctx = Secp256k1::new();
                let our_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap());
                let logger: Arc<Logger> = Arc::new(test_utils::TestLogger::new());
-               let router = Router::new(our_id, Arc::clone(&logger));
+               let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger)));
+               let router = Router::new(our_id, chain_monitor, Arc::clone(&logger));
 
                // Build network from our_id to node8:
                //