Add all_paths_failed field to PaymentFailed
[rust-lightning] / lightning / src / routing / network_graph.rs
index 2d5051166be38f127080b2364c9182fe2359a7c6..16ff80189e96b7dd249d8d96b5112b305e2f272b 100644 (file)
@@ -29,7 +29,7 @@ use ln::msgs::{QueryChannelRange, ReplyChannelRange, QueryShortChannelIds, Reply
 use ln::msgs;
 use util::ser::{Writeable, Readable, Writer};
 use util::logger::{Logger, Level};
-use util::events::{MessageSendEvent, MessageSendEventsProvider};
+use util::events::{Event, EventHandler, MessageSendEvent, MessageSendEventsProvider};
 use util::scid_utils::{block_from_scid, scid_from_parts, MAX_SCID_BLOCK};
 
 use io;
@@ -58,12 +58,80 @@ pub struct NetworkGraph {
        nodes: RwLock<BTreeMap<PublicKey, NodeInfo>>,
 }
 
+/// A read-only view of [`NetworkGraph`].
+pub struct ReadOnlyNetworkGraph<'a> {
+       channels: RwLockReadGuard<'a, BTreeMap<u64, ChannelInfo>>,
+       nodes: RwLockReadGuard<'a, BTreeMap<PublicKey, NodeInfo>>,
+}
+
+/// Update to the [`NetworkGraph`] based on payment failure information conveyed via the Onion
+/// return packet by a node along the route. See [BOLT #4] for details.
+///
+/// [BOLT #4]: https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md
+#[derive(Clone, Debug, PartialEq)]
+pub enum NetworkUpdate {
+       /// An error indicating a `channel_update` messages should be applied via
+       /// [`NetworkGraph::update_channel`].
+       ChannelUpdateMessage {
+               /// The update to apply via [`NetworkGraph::update_channel`].
+               msg: ChannelUpdate,
+       },
+       /// An error indicating only that a channel has been closed, which should be applied via
+       /// [`NetworkGraph::close_channel_from_update`].
+       ChannelClosed {
+               /// The short channel id of the closed channel.
+               short_channel_id: u64,
+               /// Whether the channel should be permanently removed or temporarily disabled until a new
+               /// `channel_update` message is received.
+               is_permanent: bool,
+       },
+       /// An error indicating only that a node has failed, which should be applied via
+       /// [`NetworkGraph::fail_node`].
+       NodeFailure {
+               /// The node id of the failed node.
+               node_id: PublicKey,
+               /// Whether the node should be permanently removed from consideration or can be restored
+               /// when a new `channel_update` message is received.
+               is_permanent: bool,
+       }
+}
+
+impl_writeable_tlv_based_enum_upgradable!(NetworkUpdate,
+       (0, ChannelUpdateMessage) => {
+               (0, msg, required),
+       },
+       (2, ChannelClosed) => {
+               (0, short_channel_id, required),
+               (2, is_permanent, required),
+       },
+       (4, NodeFailure) => {
+               (0, node_id, required),
+               (2, is_permanent, required),
+       },
+);
+
+impl<C: Deref, L: Deref> EventHandler for NetGraphMsgHandler<C, L>
+where C::Target: chain::Access, L::Target: Logger {
+       fn handle_event(&self, event: &Event) {
+               if let Event::PaymentFailed { payment_hash: _, rejected_by_dest: _, network_update, .. } = event {
+                       if let Some(network_update) = network_update {
+                               self.handle_network_update(network_update);
+                       }
+               }
+       }
+}
+
 /// Receives and validates network updates from peers,
 /// stores authentic and relevant data as a network graph.
 /// This network graph is then used for routing payments.
 /// Provides interface to help with initial routing sync by
 /// serving historical announcements.
-pub struct NetGraphMsgHandler<C: Deref, L: Deref> where C::Target: chain::Access, L::Target: Logger {
+///
+/// Serves as an [`EventHandler`] for applying updates from [`Event::PaymentFailed`] to the
+/// [`NetworkGraph`].
+pub struct NetGraphMsgHandler<C: Deref, L: Deref>
+where C::Target: chain::Access, L::Target: Logger
+{
        secp_ctx: Secp256k1<secp256k1::VerifyOnly>,
        /// Representation of the payment channel network
        pub network_graph: NetworkGraph,
@@ -73,26 +141,15 @@ pub struct NetGraphMsgHandler<C: Deref, L: Deref> where C::Target: chain::Access
        logger: L,
 }
 
-impl<C: Deref, L: Deref> NetGraphMsgHandler<C, L> where C::Target: chain::Access, L::Target: Logger {
+impl<C: Deref, L: Deref> NetGraphMsgHandler<C, L>
+where C::Target: chain::Access, L::Target: Logger
+{
        /// Creates a new tracker of the actual state of the network of channels and nodes,
-       /// assuming a fresh network graph.
+       /// assuming an existing Network Graph.
        /// Chain monitor is used to make sure announced channels exist on-chain,
        /// channel data is correct, and that the announcement is signed with
        /// channel owners' keys.
-       pub fn new(genesis_hash: BlockHash, chain_access: Option<C>, logger: L) -> Self {
-               NetGraphMsgHandler {
-                       secp_ctx: Secp256k1::verification_only(),
-                       network_graph: NetworkGraph::new(genesis_hash),
-                       full_syncs_requested: AtomicUsize::new(0),
-                       chain_access,
-                       pending_events: Mutex::new(vec![]),
-                       logger,
-               }
-       }
-
-       /// 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_access: Option<C>, logger: L, network_graph: NetworkGraph) -> Self {
+       pub fn new(network_graph: NetworkGraph, chain_access: Option<C>, logger: L) -> Self {
                NetGraphMsgHandler {
                        secp_ctx: Secp256k1::verification_only(),
                        network_graph,
@@ -121,6 +178,29 @@ impl<C: Deref, L: Deref> NetGraphMsgHandler<C, L> where C::Target: chain::Access
                        false
                }
        }
+
+       /// Applies changes to the [`NetworkGraph`] from the given update.
+       fn handle_network_update(&self, update: &NetworkUpdate) {
+               match *update {
+                       NetworkUpdate::ChannelUpdateMessage { ref msg } => {
+                               let short_channel_id = msg.contents.short_channel_id;
+                               let is_enabled = msg.contents.flags & (1 << 1) != (1 << 1);
+                               let status = if is_enabled { "enabled" } else { "disabled" };
+                               log_debug!(self.logger, "Updating channel with channel_update from a payment failure. Channel {} is {}.", short_channel_id, status);
+                               let _ = self.network_graph.update_channel(msg, &self.secp_ctx);
+                       },
+                       NetworkUpdate::ChannelClosed { short_channel_id, is_permanent } => {
+                               let action = if is_permanent { "Removing" } else { "Disabling" };
+                               log_debug!(self.logger, "{} channel graph entry for {} due to a payment failure.", action, short_channel_id);
+                               self.network_graph.close_channel_from_update(short_channel_id, is_permanent);
+                       },
+                       NetworkUpdate::NodeFailure { ref node_id, is_permanent } => {
+                               let action = if is_permanent { "Removing" } else { "Disabling" };
+                               log_debug!(self.logger, "{} node graph entry for {} due to a payment failure.", action, node_id);
+                               self.network_graph.fail_node(node_id, is_permanent);
+                       },
+               }
+       }
 }
 
 macro_rules! secp_verify_sig {
@@ -132,7 +212,9 @@ macro_rules! secp_verify_sig {
        };
 }
 
-impl<C: Deref , L: Deref > RoutingMessageHandler for NetGraphMsgHandler<C, L> where C::Target: chain::Access, L::Target: Logger {
+impl<C: Deref, L: Deref> RoutingMessageHandler for NetGraphMsgHandler<C, L>
+where C::Target: chain::Access, L::Target: Logger
+{
        fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<bool, LightningError> {
                self.network_graph.update_node_from_announcement(msg, &self.secp_ctx)?;
                Ok(msg.contents.excess_data.len() <=  MAX_EXCESS_BYTES_FOR_RELAY &&
@@ -146,24 +228,6 @@ impl<C: Deref , L: Deref > RoutingMessageHandler for NetGraphMsgHandler<C, L> wh
                Ok(msg.contents.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY)
        }
 
-       fn handle_htlc_fail_channel_update(&self, update: &msgs::HTLCFailChannelUpdate) {
-               match update {
-                       &msgs::HTLCFailChannelUpdate::ChannelUpdateMessage { ref msg } => {
-                               let chan_enabled = msg.contents.flags & (1 << 1) != (1 << 1);
-                               log_debug!(self.logger, "Updating channel with channel_update from a payment failure. Channel {} is {}abled.", msg.contents.short_channel_id, if chan_enabled { "en" } else { "dis" });
-                               let _ = self.network_graph.update_channel(msg, &self.secp_ctx);
-                       },
-                       &msgs::HTLCFailChannelUpdate::ChannelClosed { short_channel_id, is_permanent } => {
-                               log_debug!(self.logger, "{} channel graph entry for {} due to a payment failure.", if is_permanent { "Removing" } else { "Disabling" }, short_channel_id);
-                               self.network_graph.close_channel_from_update(short_channel_id, is_permanent);
-                       },
-                       &msgs::HTLCFailChannelUpdate::NodeFailure { ref node_id, is_permanent } => {
-                               log_debug!(self.logger, "{} node graph entry for {} due to a payment failure.", if is_permanent { "Removing" } else { "Disabling" }, node_id);
-                               self.network_graph.fail_node(node_id, is_permanent);
-                       },
-               }
-       }
-
        fn handle_channel_update(&self, msg: &msgs::ChannelUpdate) -> Result<bool, LightningError> {
                self.network_graph.update_channel(msg, &self.secp_ctx)?;
                Ok(msg.contents.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY)
@@ -171,7 +235,7 @@ impl<C: Deref , L: Deref > RoutingMessageHandler for NetGraphMsgHandler<C, L> wh
 
        fn get_next_channel_announcements(&self, starting_point: u64, batch_amount: u8) -> Vec<(ChannelAnnouncement, Option<ChannelUpdate>, Option<ChannelUpdate>)> {
                let mut result = Vec::with_capacity(batch_amount as usize);
-               let channels = self.network_graph.get_channels();
+               let channels = self.network_graph.channels.read().unwrap();
                let mut iter = channels.range(starting_point..);
                while result.len() < batch_amount as usize {
                        if let Some((_, ref chan)) = iter.next() {
@@ -199,7 +263,7 @@ impl<C: Deref , L: Deref > RoutingMessageHandler for NetGraphMsgHandler<C, L> wh
 
        fn get_next_node_announcements(&self, starting_point: Option<&PublicKey>, batch_amount: u8) -> Vec<NodeAnnouncement> {
                let mut result = Vec::with_capacity(batch_amount as usize);
-               let nodes = self.network_graph.get_nodes();
+               let nodes = self.network_graph.nodes.read().unwrap();
                let mut iter = if let Some(pubkey) = starting_point {
                                let mut iter = nodes.range((*pubkey)..);
                                iter.next();
@@ -340,7 +404,8 @@ impl<C: Deref , L: Deref > RoutingMessageHandler for NetGraphMsgHandler<C, L> wh
                // (has at least one update). A peer may still want to know the channel
                // exists even if its not yet routable.
                let mut batches: Vec<Vec<u64>> = vec![Vec::with_capacity(MAX_SCIDS_PER_REPLY)];
-               for (_, ref chan) in self.network_graph.get_channels().range(inclusive_start_scid.unwrap()..exclusive_end_scid.unwrap()) {
+               let channels = self.network_graph.channels.read().unwrap();
+               for (_, ref chan) in channels.range(inclusive_start_scid.unwrap()..exclusive_end_scid.unwrap()) {
                        if let Some(chan_announcement) = &chan.announcement_message {
                                // Construct a new batch if last one is full
                                if batches.last().unwrap().len() == batches.last().unwrap().capacity() {
@@ -351,6 +416,7 @@ impl<C: Deref , L: Deref > RoutingMessageHandler for NetGraphMsgHandler<C, L> wh
                                batch.push(chan_announcement.contents.short_channel_id);
                        }
                }
+               drop(channels);
 
                let mut pending_events = self.pending_events.lock().unwrap();
                let batch_count = batches.len();
@@ -662,34 +728,6 @@ impl PartialEq for NetworkGraph {
 }
 
 impl NetworkGraph {
-       /// Returns all known valid channels' short ids along with announced channel info.
-       ///
-       /// (C-not exported) because we have no mapping for `BTreeMap`s
-       pub fn get_channels(&self) -> RwLockReadGuard<'_, BTreeMap<u64, ChannelInfo>> {
-               self.channels.read().unwrap()
-       }
-
-       /// Returns all known nodes' public keys along with announced node info.
-       ///
-       /// (C-not exported) because we have no mapping for `BTreeMap`s
-       pub fn get_nodes(&self) -> RwLockReadGuard<'_, BTreeMap<PublicKey, NodeInfo>> {
-               self.nodes.read().unwrap()
-       }
-
-       /// Get network addresses by node id.
-       /// Returns None if the requested node is completely unknown,
-       /// or if node announcement for the node was never received.
-       ///
-       /// (C-not exported) as there is no practical way to track lifetimes of returned values.
-       pub fn get_addresses(&self, pubkey: &PublicKey) -> Option<Vec<NetAddress>> {
-               if let Some(node) = self.nodes.read().unwrap().get(pubkey) {
-                       if let Some(node_info) = node.announcement_info.as_ref() {
-                               return Some(node_info.addresses.clone())
-                       }
-               }
-               None
-       }
-
        /// Creates a new, empty, network graph.
        pub fn new(genesis_hash: BlockHash) -> NetworkGraph {
                Self {
@@ -699,6 +737,16 @@ impl NetworkGraph {
                }
        }
 
+       /// Returns a read-only view of the network graph.
+       pub fn read_only(&'_ self) -> ReadOnlyNetworkGraph<'_> {
+               let channels = self.channels.read().unwrap();
+               let nodes = self.nodes.read().unwrap();
+               ReadOnlyNetworkGraph {
+                       channels,
+                       nodes,
+               }
+       }
+
        /// For an already known node (from channel announcements), update its stored properties from a
        /// given node announcement.
        ///
@@ -908,7 +956,8 @@ impl NetworkGraph {
                }
        }
 
-       fn fail_node(&self, _node_id: &PublicKey, is_permanent: bool) {
+       /// Marks a node in the graph as failed.
+       pub fn fail_node(&self, _node_id: &PublicKey, is_permanent: bool) {
                if is_permanent {
                        // TODO: Wholly remove the node
                } else {
@@ -1064,18 +1113,49 @@ impl NetworkGraph {
        }
 }
 
+impl ReadOnlyNetworkGraph<'_> {
+       /// Returns all known valid channels' short ids along with announced channel info.
+       ///
+       /// (C-not exported) because we have no mapping for `BTreeMap`s
+       pub fn channels(&self) -> &BTreeMap<u64, ChannelInfo> {
+               &*self.channels
+       }
+
+       /// Returns all known nodes' public keys along with announced node info.
+       ///
+       /// (C-not exported) because we have no mapping for `BTreeMap`s
+       pub fn nodes(&self) -> &BTreeMap<PublicKey, NodeInfo> {
+               &*self.nodes
+       }
+
+       /// Get network addresses by node id.
+       /// Returns None if the requested node is completely unknown,
+       /// or if node announcement for the node was never received.
+       ///
+       /// (C-not exported) as there is no practical way to track lifetimes of returned values.
+       pub fn get_addresses(&self, pubkey: &PublicKey) -> Option<&Vec<NetAddress>> {
+               if let Some(node) = self.nodes.get(pubkey) {
+                       if let Some(node_info) = node.announcement_info.as_ref() {
+                               return Some(&node_info.addresses)
+                       }
+               }
+               None
+       }
+}
+
 #[cfg(test)]
 mod tests {
        use chain;
+       use ln::PaymentHash;
        use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
-       use routing::network_graph::{NetGraphMsgHandler, NetworkGraph, MAX_EXCESS_BYTES_FOR_RELAY};
+       use routing::network_graph::{NetGraphMsgHandler, NetworkGraph, NetworkUpdate, MAX_EXCESS_BYTES_FOR_RELAY};
        use ln::msgs::{Init, OptionalField, RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
-               UnsignedChannelAnnouncement, ChannelAnnouncement, UnsignedChannelUpdate, ChannelUpdate, HTLCFailChannelUpdate,
+               UnsignedChannelAnnouncement, ChannelAnnouncement, UnsignedChannelUpdate, ChannelUpdate, 
                ReplyChannelRange, ReplyShortChannelIdsEnd, QueryChannelRange, QueryShortChannelIds, MAX_VALUE_MSAT};
        use util::test_utils;
        use util::logger::Logger;
        use util::ser::{Readable, Writeable};
-       use util::events::{MessageSendEvent, MessageSendEventsProvider};
+       use util::events::{Event, EventHandler, MessageSendEvent, MessageSendEventsProvider};
        use util::scid_utils::scid_from_parts;
 
        use bitcoin::hashes::sha256d::Hash as Sha256dHash;
@@ -1099,7 +1179,8 @@ mod tests {
                let secp_ctx = Secp256k1::new();
                let logger = Arc::new(test_utils::TestLogger::new());
                let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
-               let net_graph_msg_handler = NetGraphMsgHandler::new(genesis_hash, None, Arc::clone(&logger));
+               let network_graph = NetworkGraph::new(genesis_hash);
+               let net_graph_msg_handler = NetGraphMsgHandler::new(network_graph, None, Arc::clone(&logger));
                (secp_ctx, net_graph_msg_handler)
        }
 
@@ -1260,7 +1341,8 @@ mod tests {
                };
 
                // Test if the UTXO lookups were not supported
-               let mut net_graph_msg_handler = NetGraphMsgHandler::new(genesis_block(Network::Testnet).header.block_hash(), None, Arc::clone(&logger));
+               let network_graph = NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash());
+               let mut net_graph_msg_handler = NetGraphMsgHandler::new(network_graph, None, Arc::clone(&logger));
                match net_graph_msg_handler.handle_channel_announcement(&valid_announcement) {
                        Ok(res) => assert!(res),
                        _ => panic!()
@@ -1268,7 +1350,7 @@ mod tests {
 
                {
                        let network = &net_graph_msg_handler.network_graph;
-                       match network.get_channels().get(&unsigned_announcement.short_channel_id) {
+                       match network.read_only().channels().get(&unsigned_announcement.short_channel_id) {
                                None => panic!(),
                                Some(_) => ()
                        };
@@ -1284,7 +1366,8 @@ mod tests {
                // Test if an associated transaction were not on-chain (or not confirmed).
                let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Testnet));
                *chain_source.utxo_ret.lock().unwrap() = Err(chain::AccessError::UnknownTx);
-               net_graph_msg_handler = NetGraphMsgHandler::new(chain_source.clone().genesis_hash, Some(chain_source.clone()), Arc::clone(&logger));
+               let network_graph = NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash());
+               net_graph_msg_handler = NetGraphMsgHandler::new(network_graph, Some(chain_source.clone()), Arc::clone(&logger));
                unsigned_announcement.short_channel_id += 1;
 
                msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]);
@@ -1320,7 +1403,7 @@ mod tests {
 
                {
                        let network = &net_graph_msg_handler.network_graph;
-                       match network.get_channels().get(&unsigned_announcement.short_channel_id) {
+                       match network.read_only().channels().get(&unsigned_announcement.short_channel_id) {
                                None => panic!(),
                                Some(_) => ()
                        };
@@ -1351,7 +1434,7 @@ mod tests {
                };
                {
                        let network = &net_graph_msg_handler.network_graph;
-                       match network.get_channels().get(&unsigned_announcement.short_channel_id) {
+                       match network.read_only().channels().get(&unsigned_announcement.short_channel_id) {
                                Some(channel_entry) => {
                                        assert_eq!(channel_entry.features, ChannelFeatures::empty());
                                },
@@ -1408,7 +1491,8 @@ mod tests {
                let secp_ctx = Secp256k1::new();
                let logger: Arc<Logger> = Arc::new(test_utils::TestLogger::new());
                let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Testnet));
-               let net_graph_msg_handler = NetGraphMsgHandler::new(genesis_block(Network::Testnet).header.block_hash(), Some(chain_source.clone()), Arc::clone(&logger));
+               let network_graph = NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash());
+               let net_graph_msg_handler = NetGraphMsgHandler::new(network_graph, Some(chain_source.clone()), Arc::clone(&logger));
 
                let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
                let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
@@ -1481,7 +1565,7 @@ mod tests {
 
                {
                        let network = &net_graph_msg_handler.network_graph;
-                       match network.get_channels().get(&short_channel_id) {
+                       match network.read_only().channels().get(&short_channel_id) {
                                None => panic!(),
                                Some(channel_info) => {
                                        assert_eq!(channel_info.one_to_two.as_ref().unwrap().cltv_expiry_delta, 144);
@@ -1572,8 +1656,14 @@ mod tests {
        }
 
        #[test]
-       fn handling_htlc_fail_channel_update() {
-               let (secp_ctx, net_graph_msg_handler) = create_net_graph_msg_handler();
+       fn handling_network_update() {
+               let logger = test_utils::TestLogger::new();
+               let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Testnet));
+               let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
+               let network_graph = NetworkGraph::new(genesis_hash);
+               let net_graph_msg_handler = NetGraphMsgHandler::new(network_graph, Some(chain_source.clone()), &logger);
+               let secp_ctx = Secp256k1::new();
+
                let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
                let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
                let node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_1_privkey);
@@ -1583,11 +1673,11 @@ mod tests {
 
                let short_channel_id = 0;
                let chain_hash = genesis_block(Network::Testnet).header.block_hash();
+               let network_graph = &net_graph_msg_handler.network_graph;
 
                {
                        // There is no nodes in the table at the beginning.
-                       let network = &net_graph_msg_handler.network_graph;
-                       assert_eq!(network.get_nodes().len(), 0);
+                       assert_eq!(network_graph.read_only().nodes().len(), 0);
                }
 
                {
@@ -1611,10 +1701,9 @@ mod tests {
                                bitcoin_signature_2: secp_ctx.sign(&msghash, node_2_btckey),
                                contents: unsigned_announcement.clone(),
                        };
-                       match net_graph_msg_handler.handle_channel_announcement(&valid_channel_announcement) {
-                               Ok(_) => (),
-                               Err(_) => panic!()
-                       };
+                       let chain_source: Option<&test_utils::TestChainSource> = None;
+                       assert!(network_graph.update_channel_from_announcement(&valid_channel_announcement, &chain_source, &secp_ctx).is_ok());
+                       assert!(network_graph.read_only().channels().get(&short_channel_id).is_some());
 
                        let unsigned_channel_update = UnsignedChannelUpdate {
                                chain_hash,
@@ -1634,34 +1723,44 @@ mod tests {
                                contents: unsigned_channel_update.clone()
                        };
 
-                       match net_graph_msg_handler.handle_channel_update(&valid_channel_update) {
-                               Ok(res) => assert!(res),
-                               _ => panic!()
-                       };
+                       assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_none());
+
+                       net_graph_msg_handler.handle_event(&Event::PaymentFailed {
+                               payment_hash: PaymentHash([0; 32]),
+                               rejected_by_dest: false,
+                               all_paths_failed: true,
+                               network_update: Some(NetworkUpdate::ChannelUpdateMessage {
+                                       msg: valid_channel_update,
+                               }),
+                               error_code: None,
+                               error_data: None,
+                       });
+
+                       assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_some());
                }
 
                // Non-permanent closing just disables a channel
                {
-                       let network = &net_graph_msg_handler.network_graph;
-                       match network.get_channels().get(&short_channel_id) {
+                       match network_graph.read_only().channels().get(&short_channel_id) {
                                None => panic!(),
                                Some(channel_info) => {
-                                       assert!(channel_info.one_to_two.is_some());
+                                       assert!(channel_info.one_to_two.as_ref().unwrap().enabled);
                                }
                        };
-               }
-
-               let channel_close_msg = HTLCFailChannelUpdate::ChannelClosed {
-                       short_channel_id,
-                       is_permanent: false
-               };
 
-               net_graph_msg_handler.handle_htlc_fail_channel_update(&channel_close_msg);
+                       net_graph_msg_handler.handle_event(&Event::PaymentFailed {
+                               payment_hash: PaymentHash([0; 32]),
+                               rejected_by_dest: false,
+                               all_paths_failed: true,
+                               network_update: Some(NetworkUpdate::ChannelClosed {
+                                       short_channel_id,
+                                       is_permanent: false,
+                               }),
+                               error_code: None,
+                               error_data: None,
+                       });
 
-               // Non-permanent closing just disables a channel
-               {
-                       let network = &net_graph_msg_handler.network_graph;
-                       match network.get_channels().get(&short_channel_id) {
+                       match network_graph.read_only().channels().get(&short_channel_id) {
                                None => panic!(),
                                Some(channel_info) => {
                                        assert!(!channel_info.one_to_two.as_ref().unwrap().enabled);
@@ -1669,21 +1768,25 @@ mod tests {
                        };
                }
 
-               let channel_close_msg = HTLCFailChannelUpdate::ChannelClosed {
-                       short_channel_id,
-                       is_permanent: true
-               };
-
-               net_graph_msg_handler.handle_htlc_fail_channel_update(&channel_close_msg);
-
                // Permanent closing deletes a channel
                {
-                       let network = &net_graph_msg_handler.network_graph;
-                       assert_eq!(network.get_channels().len(), 0);
+                       net_graph_msg_handler.handle_event(&Event::PaymentFailed {
+                               payment_hash: PaymentHash([0; 32]),
+                               rejected_by_dest: false,
+                               all_paths_failed: true,
+                               network_update: Some(NetworkUpdate::ChannelClosed {
+                                       short_channel_id,
+                                       is_permanent: true,
+                               }),
+                               error_code: None,
+                               error_data: None,
+                       });
+
+                       assert_eq!(network_graph.read_only().channels().len(), 0);
                        // Nodes are also deleted because there are no associated channels anymore
-                       assert_eq!(network.get_nodes().len(), 0);
+                       assert_eq!(network_graph.read_only().nodes().len(), 0);
                }
-               // TODO: Test HTLCFailChannelUpdate::NodeFailure, which is not implemented yet.
+               // TODO: Test NetworkUpdate::NodeFailure, which is not implemented yet.
        }
 
        #[test]
@@ -1998,8 +2101,8 @@ mod tests {
 
                let network = &net_graph_msg_handler.network_graph;
                let mut w = test_utils::TestVecWriter(Vec::new());
-               assert!(!network.get_nodes().is_empty());
-               assert!(!network.get_channels().is_empty());
+               assert!(!network.read_only().nodes().is_empty());
+               assert!(!network.read_only().channels().is_empty());
                network.write(&mut w).unwrap();
                assert!(<NetworkGraph>::read(&mut io::Cursor::new(&w.0)).unwrap() == *network);
        }