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;
+ #[cfg(feature = "std")]
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::{MessageSendEvent, MessageSendEventsProvider};
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,
// 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]),