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;
/// 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<G: Deref<Target=NetworkGraph<L>>, C: Deref, L: Deref>
where C::Target: chain::Access, L::Target: Logger
{
}
}
-impl<L: Deref> EventHandler for NetworkGraph<L> 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<L: Deref> NetworkGraph<L> 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);
+ };
+ },
}
}
}
impl Readable for ChannelUpdateInfo {
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
- 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),
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)
impl Readable for ChannelInfo {
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
- 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<ChannelUpdateInfoDeserWrapper> = None;
- init_tlv_field_var!(node_two, required);
+ _init_tlv_field_var!(node_two, required);
let mut two_to_one_wrap: Option<ChannelUpdateInfoDeserWrapper> = 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)),
});
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)),
})
}
}
impl Readable for NodeInfo {
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
- init_tlv_field_var!(lowest_inbound_channel_fees, option);
+ _init_tlv_field_var!(lowest_inbound_channel_fees, option);
let mut announcement_info_wrap: Option<NodeAnnouncementInfoDeserWrapper> = 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),
});
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),
})
}
}
#[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<u64>) {
let mut channels = self.channels.write().unwrap();
if is_permanent {
if let Some(chan) = channels.remove(&short_channel_id) {
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;
fn get_signed_node_announcement<F: Fn(&mut UnsignedNodeAnnouncement)>(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> 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],
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,
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());
}
};
- 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) {
}
// 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);
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);
// 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"))]
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 {
// 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()),
// 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()),
// 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]),