Add test coverage ChannelClosed event fields
[rust-lightning] / lightning / src / ln / peer_handler.rs
index a7f35a59c275baeb70ca6fdb607fe85283c4e965..1a39bbb3ae408e7047159e6d9f3f63267188b61f 100644 (file)
@@ -15,6 +15,7 @@
 //! call into the provided message handlers (probably a ChannelManager and P2PGossipSync) with
 //! messages they should handle, and encoding/sending response messages.
 
+use bitcoin::blockdata::constants::ChainHash;
 use bitcoin::secp256k1::{self, Secp256k1, SecretKey, PublicKey};
 
 use crate::sign::{KeysManager, NodeSigner, Recipient};
@@ -27,10 +28,11 @@ use crate::util::ser::{VecWriter, Writeable, Writer};
 use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep};
 use crate::ln::wire;
 use crate::ln::wire::{Encode, Type};
-use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
+use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, OffersMessage, OffersMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
 use crate::routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, NodeAlias};
 use crate::util::atomic_counter::AtomicCounter;
 use crate::util::logger::Logger;
+use crate::util::string::PrintableString;
 
 use crate::prelude::*;
 use crate::io;
@@ -116,9 +118,12 @@ impl OnionMessageHandler for IgnoringMessageHandler {
                InitFeatures::empty()
        }
 }
+impl OffersMessageHandler for IgnoringMessageHandler {
+       fn handle_message(&self, _msg: OffersMessage) -> Option<OffersMessage> { None }
+}
 impl CustomOnionMessageHandler for IgnoringMessageHandler {
        type CustomMessage = Infallible;
-       fn handle_custom_message(&self, _msg: Infallible) {
+       fn handle_custom_message(&self, _msg: Infallible) -> Option<Infallible> {
                // Since we always return `None` in the read the handle method should never be called.
                unreachable!();
        }
@@ -273,6 +278,13 @@ impl ChannelMessageHandler for ErroringMessageHandler {
                features
        }
 
+       fn get_genesis_hashes(&self) -> Option<Vec<ChainHash>> {
+               // We don't enforce any chains upon peer connection for `ErroringMessageHandler` and leave it up
+               // to users of `ErroringMessageHandler` to make decisions on network compatiblility.
+               // There's not really any way to pull in specific networks here, and hardcoding can cause breakages.
+               None
+       }
+
        fn handle_open_channel_v2(&self, their_node_id: &PublicKey, msg: &msgs::OpenChannelV2) {
                ErroringMessageHandler::push_error(self, their_node_id, msg.temporary_channel_id);
        }
@@ -595,7 +607,15 @@ impl Peer {
 /// issues such as overly long function definitions.
 ///
 /// This is not exported to bindings users as `Arc`s don't make sense in bindings.
-pub type SimpleArcPeerManager<SD, M, T, F, C, L> = PeerManager<SD, Arc<SimpleArcChannelManager<M, T, F, L>>, Arc<P2PGossipSync<Arc<NetworkGraph<Arc<L>>>, Arc<C>, Arc<L>>>, Arc<SimpleArcOnionMessenger<L>>, Arc<L>, IgnoringMessageHandler, Arc<KeysManager>>;
+pub type SimpleArcPeerManager<SD, M, T, F, C, L> = PeerManager<
+       SD,
+       Arc<SimpleArcChannelManager<M, T, F, L>>,
+       Arc<P2PGossipSync<Arc<NetworkGraph<Arc<L>>>, Arc<C>, Arc<L>>>,
+       Arc<SimpleArcOnionMessenger<L>>,
+       Arc<L>,
+       IgnoringMessageHandler,
+       Arc<KeysManager>
+>;
 
 /// SimpleRefPeerManager is a type alias for a PeerManager reference, and is the reference
 /// counterpart to the SimpleArcPeerManager type alias. Use this type by default when you don't
@@ -605,12 +625,25 @@ pub type SimpleArcPeerManager<SD, M, T, F, C, L> = PeerManager<SD, Arc<SimpleArc
 /// helps with issues such as long function definitions.
 ///
 /// This is not exported to bindings users as general type aliases don't make sense in bindings.
-pub type SimpleRefPeerManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, SD, M, T, F, C, L> = PeerManager<SD, SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'm, M, T, F, L>, &'f P2PGossipSync<&'g NetworkGraph<&'f L>, &'h C, &'f L>, &'i SimpleRefOnionMessenger<'j, 'k, L>, &'f L, IgnoringMessageHandler, &'c KeysManager>;
+pub type SimpleRefPeerManager<
+       'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, SD, M, T, F, C, L
+> = PeerManager<
+       SD,
+       &'n SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'm, M, T, F, L>,
+       &'f P2PGossipSync<&'g NetworkGraph<&'f L>, &'h C, &'f L>,
+       &'i SimpleRefOnionMessenger<'g, 'm, 'n, L>,
+       &'f L,
+       IgnoringMessageHandler,
+       &'c KeysManager
+>;
 
 
 /// A generic trait which is implemented for all [`PeerManager`]s. This makes bounding functions or
 /// structs on any [`PeerManager`] much simpler as only this trait is needed as a bound, rather
 /// than the full set of bounds on [`PeerManager`] itself.
+///
+/// This is not exported to bindings users as general cover traits aren't useful in other
+/// languages.
 #[allow(missing_docs)]
 pub trait APeerManager {
        type Descriptor: SocketDescriptor;
@@ -1333,7 +1366,8 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                                peer.set_their_node_id(their_node_id);
                                                                insert_node_id!();
                                                                let features = self.init_features(&their_node_id);
-                                                               let resp = msgs::Init { features, remote_network_address: filter_addresses(peer.their_net_address.clone()) };
+                                                               let networks = self.message_handler.chan_handler.get_genesis_hashes();
+                                                               let resp = msgs::Init { features, networks, remote_network_address: filter_addresses(peer.their_net_address.clone()) };
                                                                self.enqueue_message(peer, &resp);
                                                                peer.awaiting_pong_timer_tick_intervals = 0;
                                                        },
@@ -1345,7 +1379,8 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                                peer.set_their_node_id(their_node_id);
                                                                insert_node_id!();
                                                                let features = self.init_features(&their_node_id);
-                                                               let resp = msgs::Init { features, remote_network_address: filter_addresses(peer.their_net_address.clone()) };
+                                                               let networks = self.message_handler.chan_handler.get_genesis_hashes();
+                                                               let resp = msgs::Init { features, networks, remote_network_address: filter_addresses(peer.their_net_address.clone()) };
                                                                self.enqueue_message(peer, &resp);
                                                                peer.awaiting_pong_timer_tick_intervals = 0;
                                                        },
@@ -1460,6 +1495,25 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
 
                // Need an Init as first message
                if let wire::Message::Init(msg) = message {
+                       // Check if we have any compatible chains if the `networks` field is specified.
+                       if let Some(networks) = &msg.networks {
+                               if let Some(our_chains) = self.message_handler.chan_handler.get_genesis_hashes() {
+                                       let mut have_compatible_chains = false;
+                                       'our_chains: for our_chain in our_chains.iter() {
+                                               for their_chain in networks {
+                                                       if our_chain == their_chain {
+                                                               have_compatible_chains = true;
+                                                               break 'our_chains;
+                                                       }
+                                               }
+                                       }
+                                       if !have_compatible_chains {
+                                               log_debug!(self.logger, "Peer does not support any of our supported chains");
+                                               return Err(PeerHandleError { }.into());
+                                       }
+                               }
+                       }
+
                        let our_features = self.init_features(&their_node_id);
                        if msg.features.requires_unknown_bits_from(&our_features) {
                                log_debug!(self.logger, "Peer requires features unknown to us");
@@ -1536,38 +1590,14 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                // Handled above
                        },
                        wire::Message::Error(msg) => {
-                               let mut data_is_printable = true;
-                               for b in msg.data.bytes() {
-                                       if b < 32 || b > 126 {
-                                               data_is_printable = false;
-                                               break;
-                                       }
-                               }
-
-                               if data_is_printable {
-                                       log_debug!(self.logger, "Got Err message from {}: {}", log_pubkey!(their_node_id), msg.data);
-                               } else {
-                                       log_debug!(self.logger, "Got Err message from {} with non-ASCII error message", log_pubkey!(their_node_id));
-                               }
+                               log_debug!(self.logger, "Got Err message from {}: {}", log_pubkey!(their_node_id), PrintableString(&msg.data));
                                self.message_handler.chan_handler.handle_error(&their_node_id, &msg);
                                if msg.channel_id == [0; 32] {
                                        return Err(PeerHandleError { }.into());
                                }
                        },
                        wire::Message::Warning(msg) => {
-                               let mut data_is_printable = true;
-                               for b in msg.data.bytes() {
-                                       if b < 32 || b > 126 {
-                                               data_is_printable = false;
-                                               break;
-                                       }
-                               }
-
-                               if data_is_printable {
-                                       log_debug!(self.logger, "Got warning message from {}: {}", log_pubkey!(their_node_id), msg.data);
-                               } else {
-                                       log_debug!(self.logger, "Got warning message from {} with non-ASCII error message", log_pubkey!(their_node_id));
-                               }
+                               log_debug!(self.logger, "Got warning message from {}: {}", log_pubkey!(their_node_id), PrintableString(&msg.data));
                        },
 
                        wire::Message::Ping(msg) => {
@@ -2459,6 +2489,8 @@ mod tests {
        use crate::ln::msgs::{LightningError, NetAddress};
        use crate::util::test_utils;
 
+       use bitcoin::Network;
+       use bitcoin::blockdata::constants::ChainHash;
        use bitcoin::secp256k1::{PublicKey, SecretKey};
 
        use crate::prelude::*;
@@ -2537,7 +2569,7 @@ mod tests {
                        };
                        cfgs.push(
                                PeerManagerCfg{
-                                       chan_handler: test_utils::TestChannelMessageHandler::new(),
+                                       chan_handler: test_utils::TestChannelMessageHandler::new(ChainHash::using_genesis_block(Network::Testnet)),
                                        logger: test_utils::TestLogger::new(),
                                        routing_handler: test_utils::TestRoutingMessageHandler::new(),
                                        custom_handler: TestCustomMessageHandler { features },
@@ -2549,7 +2581,7 @@ mod tests {
                cfgs
        }
 
-       fn create_incompatible_peermgr_cfgs(peer_count: usize) -> Vec<PeerManagerCfg> {
+       fn create_feature_incompatible_peermgr_cfgs(peer_count: usize) -> Vec<PeerManagerCfg> {
                let mut cfgs = Vec::new();
                for i in 0..peer_count {
                        let node_secret = SecretKey::from_slice(&[42 + i as u8; 32]).unwrap();
@@ -2560,7 +2592,27 @@ mod tests {
                        };
                        cfgs.push(
                                PeerManagerCfg{
-                                       chan_handler: test_utils::TestChannelMessageHandler::new(),
+                                       chan_handler: test_utils::TestChannelMessageHandler::new(ChainHash::using_genesis_block(Network::Testnet)),
+                                       logger: test_utils::TestLogger::new(),
+                                       routing_handler: test_utils::TestRoutingMessageHandler::new(),
+                                       custom_handler: TestCustomMessageHandler { features },
+                                       node_signer: test_utils::TestNodeSigner::new(node_secret),
+                               }
+                       );
+               }
+
+               cfgs
+       }
+
+       fn create_chain_incompatible_peermgr_cfgs(peer_count: usize) -> Vec<PeerManagerCfg> {
+               let mut cfgs = Vec::new();
+               for i in 0..peer_count {
+                       let node_secret = SecretKey::from_slice(&[42 + i as u8; 32]).unwrap();
+                       let features = InitFeatures::from_le_bytes(vec![0u8; 33]);
+                       let network = ChainHash::from(&[i as u8; 32][..]);
+                       cfgs.push(
+                               PeerManagerCfg{
+                                       chan_handler: test_utils::TestChannelMessageHandler::new(network),
                                        logger: test_utils::TestLogger::new(),
                                        routing_handler: test_utils::TestRoutingMessageHandler::new(),
                                        custom_handler: TestCustomMessageHandler { features },
@@ -2703,9 +2755,9 @@ mod tests {
        }
 
        #[test]
-       fn test_incompatible_peers() {
+       fn test_feature_incompatible_peers() {
                let cfgs = create_peermgr_cfgs(2);
-               let incompatible_cfgs = create_incompatible_peermgr_cfgs(2);
+               let incompatible_cfgs = create_feature_incompatible_peermgr_cfgs(2);
 
                let peers = create_network(2, &cfgs);
                let incompatible_peers = create_network(2, &incompatible_cfgs);
@@ -2738,6 +2790,42 @@ mod tests {
                }
        }
 
+       #[test]
+       fn test_chain_incompatible_peers() {
+               let cfgs = create_peermgr_cfgs(2);
+               let incompatible_cfgs = create_chain_incompatible_peermgr_cfgs(2);
+
+               let peers = create_network(2, &cfgs);
+               let incompatible_peers = create_network(2, &incompatible_cfgs);
+               let peer_pairs = [(&peers[0], &incompatible_peers[0]), (&incompatible_peers[1], &peers[1])];
+               for (peer_a, peer_b) in peer_pairs.iter() {
+                       let id_a = peer_a.node_signer.get_node_id(Recipient::Node).unwrap();
+                       let mut fd_a = FileDescriptor {
+                               fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())),
+                               disconnect: Arc::new(AtomicBool::new(false)),
+                       };
+                       let addr_a = NetAddress::IPv4{addr: [127, 0, 0, 1], port: 1000};
+                       let mut fd_b = FileDescriptor {
+                               fd: 1, outbound_data: Arc::new(Mutex::new(Vec::new())),
+                               disconnect: Arc::new(AtomicBool::new(false)),
+                       };
+                       let addr_b = NetAddress::IPv4{addr: [127, 0, 0, 1], port: 1001};
+                       let initial_data = peer_b.new_outbound_connection(id_a, fd_b.clone(), Some(addr_a.clone())).unwrap();
+                       peer_a.new_inbound_connection(fd_a.clone(), Some(addr_b.clone())).unwrap();
+                       assert_eq!(peer_a.read_event(&mut fd_a, &initial_data).unwrap(), false);
+                       peer_a.process_events();
+
+                       let a_data = fd_a.outbound_data.lock().unwrap().split_off(0);
+                       assert_eq!(peer_b.read_event(&mut fd_b, &a_data).unwrap(), false);
+
+                       peer_b.process_events();
+                       let b_data = fd_b.outbound_data.lock().unwrap().split_off(0);
+
+                       // Should fail because of incompatible chains
+                       assert!(peer_a.read_event(&mut fd_a, &b_data).is_err());
+               }
+       }
+
        #[test]
        fn test_disconnect_peer() {
                // Simple test which builds a network of PeerManager, connects and brings them to NoiseState::Finished and
@@ -2762,8 +2850,8 @@ mod tests {
                // Simple test which builds a network of PeerManager, connects and brings them to NoiseState::Finished and
                // push a message from one peer to another.
                let cfgs = create_peermgr_cfgs(2);
-               let a_chan_handler = test_utils::TestChannelMessageHandler::new();
-               let b_chan_handler = test_utils::TestChannelMessageHandler::new();
+               let a_chan_handler = test_utils::TestChannelMessageHandler::new(ChainHash::using_genesis_block(Network::Testnet));
+               let b_chan_handler = test_utils::TestChannelMessageHandler::new(ChainHash::using_genesis_block(Network::Testnet));
                let mut peers = create_network(2, &cfgs);
                let (fd_a, mut fd_b) = establish_connection(&peers[0], &peers[1]);
                assert_eq!(peers[0].peers.read().unwrap().len(), 1);