//! The [`NetworkGraph`] stores the network gossip and [`P2PGossipSync`] fetches it from peers
use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE;
-use bitcoin::secp256k1::PublicKey;
+use bitcoin::secp256k1::{PublicKey, Verification};
use bitcoin::secp256k1::Secp256k1;
use bitcoin::secp256k1;
}
}
+/// Verifies the signature of a [`NodeAnnouncement`].
+///
+/// Returns an error if it is invalid.
+pub fn verify_node_announcement<C: Verification>(msg: &NodeAnnouncement, secp_ctx: &Secp256k1<C>) -> Result<(), LightningError> {
+ let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]);
+ secp_verify_sig!(secp_ctx, &msg_hash, &msg.signature, &get_pubkey_from_node_id!(msg.contents.node_id, "node_announcement"), "node_announcement");
+
+ Ok(())
+}
+
+/// Verifies all signatures included in a [`ChannelAnnouncement`].
+///
+/// Returns an error if one of the signatures is invalid.
+pub fn verify_channel_announcement<C: Verification>(msg: &ChannelAnnouncement, secp_ctx: &Secp256k1<C>) -> Result<(), LightningError> {
+ let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]);
+ secp_verify_sig!(secp_ctx, &msg_hash, &msg.node_signature_1, &get_pubkey_from_node_id!(msg.contents.node_id_1, "channel_announcement"), "channel_announcement");
+ secp_verify_sig!(secp_ctx, &msg_hash, &msg.node_signature_2, &get_pubkey_from_node_id!(msg.contents.node_id_2, "channel_announcement"), "channel_announcement");
+ secp_verify_sig!(secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &get_pubkey_from_node_id!(msg.contents.bitcoin_key_1, "channel_announcement"), "channel_announcement");
+ secp_verify_sig!(secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &get_pubkey_from_node_id!(msg.contents.bitcoin_key_2, "channel_announcement"), "channel_announcement");
+
+ Ok(())
+}
+
impl<G: Deref<Target=NetworkGraph<L>>, U: Deref, L: Deref> RoutingMessageHandler for P2PGossipSync<G, U, L>
where U::Target: UtxoLookup, L::Target: Logger
{
(4, self.rgb, required),
(6, self.alias, required),
(8, self.announcement_message, option),
- (10, empty_addresses, vec_type), // Versions prior to 0.0.115 require this field
+ (10, empty_addresses, required_vec), // Versions prior to 0.0.115 require this field
});
Ok(())
}
}
impl Readable for NodeAnnouncementInfo {
- fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+ fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
_init_and_read_tlv_fields!(reader, {
(0, features, required),
(2, last_update, required),
(4, rgb, required),
(6, alias, required),
(8, announcement_message, option),
- (10, _addresses, vec_type), // deprecated, not used anymore
+ (10, _addresses, optional_vec), // deprecated, not used anymore
});
let _: Option<Vec<NetAddress>> = _addresses;
Ok(Self { features: features.0.unwrap(), last_update: last_update.0.unwrap(), rgb: rgb.0.unwrap(),
alias: alias.0.unwrap(), announcement_message })
- }
+ }
}
/// A user-defined name for a node, which may be used when displaying the node in a graph.
write_tlv_fields!(writer, {
// Note that older versions of LDK wrote the lowest inbound fees here at type 0
(2, self.announcement_info, option),
- (4, self.channels, vec_type),
+ (4, self.channels, required_vec),
});
Ok(())
}
// with zero inbound fees, causing that heuristic to provide little gain. Worse, because it
// requires additional complexity and lookups during routing, it ends up being a
// performance loss. Thus, we simply ignore the old field here and no longer track it.
- let mut _lowest_inbound_channel_fees: Option<RoutingFees> = None;
- let mut announcement_info_wrap: Option<NodeAnnouncementInfoDeserWrapper> = None;
- _init_tlv_field_var!(channels, vec_type);
-
- read_tlv_fields!(reader, {
+ _init_and_read_tlv_fields!(reader, {
(0, _lowest_inbound_channel_fees, option),
(2, announcement_info_wrap, upgradable_option),
- (4, channels, vec_type),
+ (4, channels, required_vec),
});
+ let _: Option<RoutingFees> = _lowest_inbound_channel_fees;
+ let announcement_info_wrap: Option<NodeAnnouncementInfoDeserWrapper> = announcement_info_wrap;
Ok(NodeInfo {
announcement_info: announcement_info_wrap.map(|w| w.0),
- channels: _init_tlv_based_struct_field!(channels, vec_type),
+ channels,
})
}
}
/// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept
/// routing messages from a source using a protocol other than the lightning P2P protocol.
pub fn update_node_from_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<(), LightningError> {
- let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]);
- secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.signature, &get_pubkey_from_node_id!(msg.contents.node_id, "node_announcement"), "node_announcement");
+ verify_node_announcement(msg, &self.secp_ctx)?;
self.update_node_from_announcement_intern(&msg.contents, Some(&msg))
}
where
U::Target: UtxoLookup,
{
- let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]);
- secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_1, &get_pubkey_from_node_id!(msg.contents.node_id_1, "channel_announcement"), "channel_announcement");
- secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_2, &get_pubkey_from_node_id!(msg.contents.node_id_2, "channel_announcement"), "channel_announcement");
- secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &get_pubkey_from_node_id!(msg.contents.bitcoin_key_1, "channel_announcement"), "channel_announcement");
- secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &get_pubkey_from_node_id!(msg.contents.bitcoin_key_2, "channel_announcement"), "channel_announcement");
+ verify_channel_announcement(msg, &self.secp_ctx)?;
self.update_channel_from_unsigned_announcement_intern(&msg.contents, Some(msg), utxo_lookup)
}
let node_id_a = channel_info.node_one.clone();
let node_id_b = channel_info.node_two.clone();
+ log_gossip!(self.logger, "Adding channel {} between nodes {} and {}", short_channel_id, node_id_a, node_id_b);
+
match channels.entry(short_channel_id) {
IndexedMapEntry::Occupied(mut entry) => {
//TODO: because asking the blockchain if short_channel_id is valid is only optional
let mut scids_to_remove = Vec::new();
for (scid, info) in channels.unordered_iter_mut() {
if info.one_to_two.is_some() && info.one_to_two.as_ref().unwrap().last_update < min_time_unix {
+ log_gossip!(self.logger, "Removing directional update one_to_two (0) for channel {} due to its timestamp {} being below {}",
+ scid, info.one_to_two.as_ref().unwrap().last_update, min_time_unix);
info.one_to_two = None;
}
if info.two_to_one.is_some() && info.two_to_one.as_ref().unwrap().last_update < min_time_unix {
+ log_gossip!(self.logger, "Removing directional update two_to_one (1) for channel {} due to its timestamp {} being below {}",
+ scid, info.two_to_one.as_ref().unwrap().last_update, min_time_unix);
info.two_to_one = None;
}
if info.one_to_two.is_none() || info.two_to_one.is_none() {
// We check the announcement_received_time here to ensure we don't drop
// announcements that we just received and are just waiting for our peer to send a
// channel_update for.
- if info.announcement_received_time < min_time_unix as u64 {
+ let announcement_received_timestamp = info.announcement_received_time;
+ if announcement_received_timestamp < min_time_unix as u64 {
+ log_gossip!(self.logger, "Removing channel {} because both directional updates are missing and its announcement timestamp {} being below {}",
+ scid, announcement_received_timestamp, min_time_unix);
scids_to_remove.push(*scid);
}
}
}
}
+ log_gossip!(self.logger, "Updating channel {} in direction {} with timestamp {}", msg.short_channel_id, msg.flags & 1, msg.timestamp);
+
let mut channels = self.channels.write().unwrap();
match channels.get_mut(&msg.short_channel_id) {
None => {