X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Fgossip.rs;h=065472aa3c14158b1e24470490d70d7a917de84a;hb=efdd2217b78b1b5b3cbbcb8f4bce26f1c6a0cf87;hp=00846a7ba794a1e3b9ba52319d1daf97641097b6;hpb=d03640082b1c47647a273ccbeafed9a1e986d96c;p=rust-lightning diff --git a/lightning/src/routing/gossip.rs b/lightning/src/routing/gossip.rs index 00846a7b..065472aa 100644 --- a/lightning/src/routing/gossip.rs +++ b/lightning/src/routing/gossip.rs @@ -29,7 +29,7 @@ use crate::ln::msgs::{QueryChannelRange, ReplyChannelRange, QueryShortChannelIds use crate::ln::msgs; use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, MaybeReadable}; use crate::util::logger::{Logger, Level}; -use crate::util::events::{Event, EventHandler, MessageSendEvent, MessageSendEventsProvider}; +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; @@ -213,9 +213,6 @@ impl_writeable_tlv_based_enum_upgradable!(NetworkUpdate, /// This network graph is then used for routing payments. /// Provides interface to help with initial routing sync by /// serving historical announcements. -/// -/// Serves as an [`EventHandler`] for applying updates from [`Event::PaymentPathFailed`] to the -/// [`NetworkGraph`]. pub struct P2PGossipSync>, C: Deref, L: Deref> where C::Target: chain::Access, L::Target: Logger { @@ -275,32 +272,31 @@ where C::Target: chain::Access, L::Target: Logger } } -impl EventHandler for NetworkGraph where L::Target: Logger { - fn handle_event(&self, event: &Event) { - if let Event::PaymentPathFailed { network_update, .. } = event { - if let Some(network_update) = network_update { - match *network_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.update_channel(msg); - }, - NetworkUpdate::ChannelFailure { 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.channel_failed(short_channel_id, is_permanent); - }, - NetworkUpdate::NodeFailure { ref node_id, is_permanent } => { - if is_permanent { - log_debug!(self.logger, - "Removed node graph entry for {} due to a payment failure.", log_pubkey!(node_id)); - self.node_failed_permanent(node_id); - }; - }, - } - } +impl NetworkGraph where L::Target: Logger { + /// Handles any network updates originating from [`Event`]s. + /// + /// [`Event`]: crate::util::events::Event + pub fn handle_network_update(&self, network_update: &NetworkUpdate) { + match *network_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.update_channel(msg); + }, + NetworkUpdate::ChannelFailure { 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.channel_failed(short_channel_id, is_permanent); + }, + NetworkUpdate::NodeFailure { ref node_id, is_permanent } => { + if is_permanent { + log_debug!(self.logger, + "Removed node graph entry for {} due to a payment failure.", log_pubkey!(node_id)); + self.node_failed_permanent(node_id); + }; + }, } } } @@ -677,13 +673,13 @@ impl Writeable for ChannelUpdateInfo { impl Readable for ChannelUpdateInfo { fn read(reader: &mut R) -> Result { - init_tlv_field_var!(last_update, required); - init_tlv_field_var!(enabled, required); - init_tlv_field_var!(cltv_expiry_delta, required); - init_tlv_field_var!(htlc_minimum_msat, required); - init_tlv_field_var!(htlc_maximum_msat, option); - init_tlv_field_var!(fees, required); - init_tlv_field_var!(last_update_message, required); + _init_tlv_field_var!(last_update, required); + _init_tlv_field_var!(enabled, required); + _init_tlv_field_var!(cltv_expiry_delta, required); + _init_tlv_field_var!(htlc_minimum_msat, required); + _init_tlv_field_var!(htlc_maximum_msat, option); + _init_tlv_field_var!(fees, required); + _init_tlv_field_var!(last_update_message, required); read_tlv_fields!(reader, { (0, last_update, required), @@ -697,13 +693,13 @@ impl Readable for ChannelUpdateInfo { if let Some(htlc_maximum_msat) = htlc_maximum_msat { Ok(ChannelUpdateInfo { - last_update: init_tlv_based_struct_field!(last_update, required), - enabled: init_tlv_based_struct_field!(enabled, required), - cltv_expiry_delta: init_tlv_based_struct_field!(cltv_expiry_delta, required), - htlc_minimum_msat: init_tlv_based_struct_field!(htlc_minimum_msat, required), + last_update: _init_tlv_based_struct_field!(last_update, required), + enabled: _init_tlv_based_struct_field!(enabled, required), + cltv_expiry_delta: _init_tlv_based_struct_field!(cltv_expiry_delta, required), + htlc_minimum_msat: _init_tlv_based_struct_field!(htlc_minimum_msat, required), htlc_maximum_msat, - fees: init_tlv_based_struct_field!(fees, required), - last_update_message: init_tlv_based_struct_field!(last_update_message, required), + fees: _init_tlv_based_struct_field!(fees, required), + last_update_message: _init_tlv_based_struct_field!(last_update_message, required), }) } else { Err(DecodeError::InvalidValue) @@ -824,14 +820,14 @@ impl MaybeReadable for ChannelUpdateInfoDeserWrapper { impl Readable for ChannelInfo { fn read(reader: &mut R) -> Result { - init_tlv_field_var!(features, required); - init_tlv_field_var!(announcement_received_time, (default_value, 0)); - init_tlv_field_var!(node_one, required); + _init_tlv_field_var!(features, required); + _init_tlv_field_var!(announcement_received_time, (default_value, 0)); + _init_tlv_field_var!(node_one, required); let mut one_to_two_wrap: Option = None; - init_tlv_field_var!(node_two, required); + _init_tlv_field_var!(node_two, required); let mut two_to_one_wrap: Option = None; - init_tlv_field_var!(capacity_sats, required); - init_tlv_field_var!(announcement_message, required); + _init_tlv_field_var!(capacity_sats, required); + _init_tlv_field_var!(announcement_message, required); read_tlv_fields!(reader, { (0, features, required), (1, announcement_received_time, (default_value, 0)), @@ -844,14 +840,14 @@ impl Readable for ChannelInfo { }); Ok(ChannelInfo { - features: init_tlv_based_struct_field!(features, required), - node_one: init_tlv_based_struct_field!(node_one, required), + features: _init_tlv_based_struct_field!(features, required), + node_one: _init_tlv_based_struct_field!(node_one, required), one_to_two: one_to_two_wrap.map(|w| w.0).unwrap_or(None), - node_two: init_tlv_based_struct_field!(node_two, required), + node_two: _init_tlv_based_struct_field!(node_two, required), two_to_one: two_to_one_wrap.map(|w| w.0).unwrap_or(None), - capacity_sats: init_tlv_based_struct_field!(capacity_sats, required), - announcement_message: init_tlv_based_struct_field!(announcement_message, required), - announcement_received_time: init_tlv_based_struct_field!(announcement_received_time, (default_value, 0)), + capacity_sats: _init_tlv_based_struct_field!(capacity_sats, required), + announcement_message: _init_tlv_based_struct_field!(announcement_message, required), + announcement_received_time: _init_tlv_based_struct_field!(announcement_received_time, (default_value, 0)), }) } } @@ -1107,9 +1103,9 @@ impl MaybeReadable for NodeAnnouncementInfoDeserWrapper { impl Readable for NodeInfo { fn read(reader: &mut R) -> Result { - init_tlv_field_var!(lowest_inbound_channel_fees, option); + _init_tlv_field_var!(lowest_inbound_channel_fees, option); let mut announcement_info_wrap: Option = None; - init_tlv_field_var!(channels, vec_type); + _init_tlv_field_var!(channels, vec_type); read_tlv_fields!(reader, { (0, lowest_inbound_channel_fees, option), @@ -1118,9 +1114,9 @@ impl Readable for NodeInfo { }); Ok(NodeInfo { - lowest_inbound_channel_fees: init_tlv_based_struct_field!(lowest_inbound_channel_fees, option), + lowest_inbound_channel_fees: _init_tlv_based_struct_field!(lowest_inbound_channel_fees, option), announcement_info: announcement_info_wrap.map(|w| w.0), - channels: init_tlv_based_struct_field!(channels, vec_type), + channels: _init_tlv_based_struct_field!(channels, vec_type), }) } } @@ -1160,14 +1156,14 @@ impl ReadableArgs for NetworkGraph where L::Target: Logger { let genesis_hash: BlockHash = Readable::read(reader)?; let channels_count: u64 = Readable::read(reader)?; - let mut channels = BTreeMap::new(); + let mut channels: BTreeMap = BTreeMap::new(); for _ in 0..channels_count { let chan_id: u64 = Readable::read(reader)?; let chan_info = Readable::read(reader)?; channels.insert(chan_id, chan_info); } let nodes_count: u64 = Readable::read(reader)?; - let mut nodes = BTreeMap::new(); + let mut nodes: BTreeMap = BTreeMap::new(); for _ in 0..nodes_count { let node_id = Readable::read(reader)?; let node_info = Readable::read(reader)?; @@ -1179,6 +1175,22 @@ impl ReadableArgs for NetworkGraph where L::Target: Logger { (1, last_rapid_gossip_sync_timestamp, option), }); + // Regenerate inbound fees for all channels. The live-updating of these has been broken in + // various ways historically, so this ensures that we have up-to-date limits. + for (node_id, node) in nodes.iter_mut() { + let mut best_fees = RoutingFees { base_msat: u32::MAX, proportional_millionths: u32::MAX }; + for channel in node.channels.iter() { + if let Some(chan) = channels.get(channel) { + let dir_opt = if *node_id == chan.node_one { &chan.two_to_one } else { &chan.one_to_two }; + if let Some(dir) = dir_opt { + best_fees.base_msat = cmp::min(best_fees.base_msat, dir.fees.base_msat); + best_fees.proportional_millionths = cmp::min(best_fees.proportional_millionths, dir.fees.proportional_millionths); + } + } else { return Err(DecodeError::InvalidValue); } + } + node.lowest_inbound_channel_fees = Some(best_fees); + } + Ok(NetworkGraph { secp_ctx: Secp256k1::verification_only(), genesis_hash, @@ -1545,6 +1557,14 @@ impl NetworkGraph where L::Target: Logger { #[cfg(not(feature = "std"))] let current_time_unix = None; + self.channel_failed_with_time(short_channel_id, is_permanent, current_time_unix) + } + + /// Marks a channel in the graph as failed if a corresponding HTLC fail was sent. + /// 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. + fn channel_failed_with_time(&self, short_channel_id: u64, is_permanent: bool, current_time_unix: Option) { let mut channels = self.channels.write().unwrap(); if is_permanent { if let Some(chan) = channels.remove(&short_channel_id) { @@ -1931,15 +1951,15 @@ mod tests { use crate::chain; use crate::ln::channelmanager; use crate::ln::chan_utils::make_funding_redeemscript; - use crate::ln::PaymentHash; use crate::ln::features::InitFeatures; use crate::routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate, NodeAlias, MAX_EXCESS_BYTES_FOR_RELAY, NodeId, RoutingFees, ChannelUpdateInfo, ChannelInfo, NodeAnnouncementInfo, NodeInfo}; use crate::ln::msgs::{RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement, UnsignedChannelAnnouncement, ChannelAnnouncement, UnsignedChannelUpdate, ChannelUpdate, ReplyChannelRange, QueryChannelRange, QueryShortChannelIds, MAX_VALUE_MSAT}; + use crate::util::config::UserConfig; use crate::util::test_utils; use crate::util::ser::{ReadableArgs, Writeable}; - use crate::util::events::{Event, EventHandler, MessageSendEvent, MessageSendEventsProvider}; + use crate::util::events::{MessageSendEvent, MessageSendEventsProvider}; use crate::util::scid_utils::scid_from_parts; use crate::routing::gossip::REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS; @@ -1996,7 +2016,7 @@ mod tests { fn get_signed_node_announcement(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1) -> NodeAnnouncement { let node_id = PublicKey::from_secret_key(&secp_ctx, node_key); let mut unsigned_announcement = UnsignedNodeAnnouncement { - features: channelmanager::provided_node_features(), + features: channelmanager::provided_node_features(&UserConfig::default()), timestamp: 100, node_id: node_id, rgb: [0; 3], @@ -2020,7 +2040,7 @@ mod tests { let node_2_btckey = &SecretKey::from_slice(&[39; 32]).unwrap(); let mut unsigned_announcement = UnsignedChannelAnnouncement { - features: channelmanager::provided_channel_features(), + features: channelmanager::provided_channel_features(&UserConfig::default()), chain_hash: genesis_block(Network::Testnet).header.block_hash(), short_channel_id: 0, node_id_1, @@ -2383,19 +2403,8 @@ mod tests { let valid_channel_update = get_signed_channel_update(|_| {}, node_1_privkey, &secp_ctx); assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_none()); - network_graph.handle_event(&Event::PaymentPathFailed { - payment_id: None, - payment_hash: PaymentHash([0; 32]), - payment_failed_permanently: false, - all_paths_failed: true, - path: vec![], - network_update: Some(NetworkUpdate::ChannelUpdateMessage { - msg: valid_channel_update, - }), - short_channel_id: None, - retry: None, - error_code: None, - error_data: None, + network_graph.handle_network_update(&NetworkUpdate::ChannelUpdateMessage { + msg: valid_channel_update, }); assert!(network_graph.read_only().channels().get(&short_channel_id).unwrap().one_to_two.is_some()); @@ -2410,20 +2419,9 @@ mod tests { } }; - network_graph.handle_event(&Event::PaymentPathFailed { - payment_id: None, - payment_hash: PaymentHash([0; 32]), - payment_failed_permanently: false, - all_paths_failed: true, - path: vec![], - network_update: Some(NetworkUpdate::ChannelFailure { - short_channel_id, - is_permanent: false, - }), - short_channel_id: None, - retry: None, - error_code: None, - error_data: None, + network_graph.handle_network_update(&NetworkUpdate::ChannelFailure { + short_channel_id, + is_permanent: false, }); match network_graph.read_only().channels().get(&short_channel_id) { @@ -2435,20 +2433,9 @@ mod tests { } // Permanent closing deletes a channel - network_graph.handle_event(&Event::PaymentPathFailed { - payment_id: None, - payment_hash: PaymentHash([0; 32]), - payment_failed_permanently: false, - all_paths_failed: true, - path: vec![], - network_update: Some(NetworkUpdate::ChannelFailure { - short_channel_id, - is_permanent: true, - }), - short_channel_id: None, - retry: None, - error_code: None, - error_data: None, + network_graph.handle_network_update(&NetworkUpdate::ChannelFailure { + short_channel_id, + is_permanent: true, }); assert_eq!(network_graph.read_only().channels().len(), 0); @@ -2467,40 +2454,18 @@ mod tests { assert!(network_graph.read_only().channels().get(&short_channel_id).is_some()); // Non-permanent node failure does not delete any nodes or channels - network_graph.handle_event(&Event::PaymentPathFailed { - payment_id: None, - payment_hash: PaymentHash([0; 32]), - payment_failed_permanently: false, - all_paths_failed: true, - path: vec![], - network_update: Some(NetworkUpdate::NodeFailure { - node_id: node_2_id, - is_permanent: false, - }), - short_channel_id: None, - retry: None, - error_code: None, - error_data: None, + network_graph.handle_network_update(&NetworkUpdate::NodeFailure { + node_id: node_2_id, + is_permanent: false, }); assert!(network_graph.read_only().channels().get(&short_channel_id).is_some()); assert!(network_graph.read_only().nodes().get(&NodeId::from_pubkey(&node_2_id)).is_some()); // Permanent node failure deletes node and its channels - network_graph.handle_event(&Event::PaymentPathFailed { - payment_id: None, - payment_hash: PaymentHash([0; 32]), - payment_failed_permanently: false, - all_paths_failed: true, - path: vec![], - network_update: Some(NetworkUpdate::NodeFailure { - node_id: node_2_id, - is_permanent: true, - }), - short_channel_id: None, - retry: None, - error_code: None, - error_data: None, + network_graph.handle_network_update(&NetworkUpdate::NodeFailure { + node_id: node_2_id, + is_permanent: true, }); assert_eq!(network_graph.read_only().nodes().len(), 0); @@ -2597,18 +2562,18 @@ mod tests { // Mark the channel as permanently failed. This will also remove the two nodes // and all of the entries will be tracked as removed. - network_graph.channel_failed(short_channel_id, true); + network_graph.channel_failed_with_time(short_channel_id, true, Some(tracking_time)); // Should not remove from tracking if insufficient time has passed network_graph.remove_stale_channels_and_tracking_with_time( tracking_time + REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS - 1); - assert_eq!(network_graph.removed_channels.lock().unwrap().len(), 1); + assert_eq!(network_graph.removed_channels.lock().unwrap().len(), 1, "Removed channel count ≠ 1 with tracking_time {}", tracking_time); // Provide a later time so that sufficient time has passed network_graph.remove_stale_channels_and_tracking_with_time( tracking_time + REMOVED_ENTRIES_TRACKING_AGE_LIMIT_SECS); - assert!(network_graph.removed_channels.lock().unwrap().is_empty()); - assert!(network_graph.removed_nodes.lock().unwrap().is_empty()); + assert!(network_graph.removed_channels.lock().unwrap().is_empty(), "Unexpectedly removed channels with tracking_time {}", tracking_time); + assert!(network_graph.removed_nodes.lock().unwrap().is_empty(), "Unexpectedly removed nodes with tracking_time {}", tracking_time); } #[cfg(not(feature = "std"))] @@ -3209,6 +3174,7 @@ mod tests { let node_cfgs = crate::ln::functional_test_utils::create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = crate::ln::functional_test_utils::create_node_chanmgrs(2, &node_cfgs, &[None, None, None, None]); let nodes = crate::ln::functional_test_utils::create_network(2, &node_cfgs, &node_chanmgrs); + let config = crate::ln::functional_test_utils::test_default_channel_config(); // 1. Test encoding/decoding of ChannelUpdateInfo let chan_update_info = ChannelUpdateInfo { @@ -3245,7 +3211,7 @@ mod tests { // 2. Test encoding/decoding of ChannelInfo // Check we can encode/decode ChannelInfo without ChannelUpdateInfo fields present. let chan_info_none_updates = ChannelInfo { - features: channelmanager::provided_channel_features(), + features: channelmanager::provided_channel_features(&config), node_one: NodeId::from_pubkey(&nodes[0].node.get_our_node_id()), one_to_two: None, node_two: NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), @@ -3263,7 +3229,7 @@ mod tests { // Check we can encode/decode ChannelInfo with ChannelUpdateInfo fields present. let chan_info_some_updates = ChannelInfo { - features: channelmanager::provided_channel_features(), + features: channelmanager::provided_channel_features(&config), node_one: NodeId::from_pubkey(&nodes[0].node.get_our_node_id()), one_to_two: Some(chan_update_info.clone()), node_two: NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), @@ -3305,7 +3271,7 @@ mod tests { // 1. Check we can read a valid NodeAnnouncementInfo and fail on an invalid one let valid_netaddr = crate::ln::msgs::NetAddress::Hostname { hostname: crate::util::ser::Hostname::try_from("A".to_string()).unwrap(), port: 1234 }; let valid_node_ann_info = NodeAnnouncementInfo { - features: channelmanager::provided_node_features(), + features: channelmanager::provided_node_features(&UserConfig::default()), last_update: 0, rgb: [0u8; 3], alias: NodeAlias([0u8; 32]),