use ln::msgs::{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, OptionalField, GossipTimestampFilter};
use ln::msgs::{QueryChannelRange, ReplyChannelRange, QueryShortChannelIds, ReplyShortChannelIdsEnd};
use ln::msgs;
-use util::ser::{Writeable, Readable, Writer};
+use util::ser::{Readable, ReadableArgs, Writeable, Writer};
use util::logger::{Logger, Level};
use util::events::{Event, EventHandler, MessageSendEvent, MessageSendEventsProvider};
use util::scid_utils::{block_from_scid, scid_from_parts, MAX_SCID_BLOCK};
}
/// Represents the network as nodes and channels between them
-pub struct NetworkGraph {
+pub struct NetworkGraph<L: Deref> where L::Target: Logger {
+ secp_ctx: Secp256k1<secp256k1::VerifyOnly>,
last_rapid_gossip_sync_timestamp: Mutex<Option<u32>>,
genesis_hash: BlockHash,
+ logger: L,
// Lock order: channels -> nodes
channels: RwLock<BTreeMap<u64, ChannelInfo>>,
nodes: RwLock<BTreeMap<NodeId, NodeInfo>>,
}
-impl Clone for NetworkGraph {
- fn clone(&self) -> Self {
- let channels = self.channels.read().unwrap();
- let nodes = self.nodes.read().unwrap();
- let last_rapid_gossip_sync_timestamp = self.get_last_rapid_gossip_sync_timestamp();
- Self {
- genesis_hash: self.genesis_hash.clone(),
- channels: RwLock::new(channels.clone()),
- nodes: RwLock::new(nodes.clone()),
- last_rapid_gossip_sync_timestamp: Mutex::new(last_rapid_gossip_sync_timestamp)
- }
- }
-}
-
/// A read-only view of [`NetworkGraph`].
pub struct ReadOnlyNetworkGraph<'a> {
channels: RwLockReadGuard<'a, BTreeMap<u64, ChannelInfo>>,
},
);
-impl<G: Deref<Target=NetworkGraph>, C: Deref, L: Deref> EventHandler for P2PGossipSync<G, C, L>
-where C::Target: chain::Access, L::Target: Logger {
- fn handle_event(&self, event: &Event) {
- if let Event::PaymentPathFailed { 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.
///
/// Serves as an [`EventHandler`] for applying updates from [`Event::PaymentPathFailed`] to the
/// [`NetworkGraph`].
-pub struct P2PGossipSync<G: Deref<Target=NetworkGraph>, C: Deref, L: Deref>
+pub struct P2PGossipSync<G: Deref<Target=NetworkGraph<L>>, C: Deref, L: Deref>
where C::Target: chain::Access, L::Target: Logger
{
- secp_ctx: Secp256k1<secp256k1::VerifyOnly>,
network_graph: G,
chain_access: Option<C>,
full_syncs_requested: AtomicUsize,
logger: L,
}
-impl<G: Deref<Target=NetworkGraph>, C: Deref, L: Deref> P2PGossipSync<G, C, L>
+impl<G: Deref<Target=NetworkGraph<L>>, C: Deref, L: Deref> P2PGossipSync<G, 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,
/// channel owners' keys.
pub fn new(network_graph: G, chain_access: Option<C>, logger: L) -> Self {
P2PGossipSync {
- secp_ctx: Secp256k1::verification_only(),
network_graph,
full_syncs_requested: AtomicUsize::new(0),
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::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.network_graph.channel_failed(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.node_failed(node_id, is_permanent);
- },
+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 } => {
+ 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.node_failed(node_id, is_permanent);
+ },
+ }
+ }
}
}
}
};
}
-impl<G: Deref<Target=NetworkGraph>, C: Deref, L: Deref> RoutingMessageHandler for P2PGossipSync<G, C, L>
+impl<G: Deref<Target=NetworkGraph<L>>, C: Deref, L: Deref> RoutingMessageHandler for P2PGossipSync<G, 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)?;
+ self.network_graph.update_node_from_announcement(msg)?;
Ok(msg.contents.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY &&
msg.contents.excess_address_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY &&
msg.contents.excess_data.len() + msg.contents.excess_address_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY)
}
fn handle_channel_announcement(&self, msg: &msgs::ChannelAnnouncement) -> Result<bool, LightningError> {
- self.network_graph.update_channel_from_announcement(msg, &self.chain_access, &self.secp_ctx)?;
+ self.network_graph.update_channel_from_announcement(msg, &self.chain_access)?;
log_gossip!(self.logger, "Added channel_announcement for {}{}", msg.contents.short_channel_id, if !msg.contents.excess_data.is_empty() { " with excess uninterpreted data!" } else { "" });
Ok(msg.contents.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY)
}
fn handle_channel_update(&self, msg: &msgs::ChannelUpdate) -> Result<bool, LightningError> {
- self.network_graph.update_channel(msg, &self.secp_ctx)?;
+ self.network_graph.update_channel(msg)?;
Ok(msg.contents.excess_data.len() <= MAX_EXCESS_BYTES_FOR_RELAY)
}
}
}
-impl<G: Deref<Target=NetworkGraph>, C: Deref, L: Deref> MessageSendEventsProvider for P2PGossipSync<G, C, L>
+impl<G: Deref<Target=NetworkGraph<L>>, C: Deref, L: Deref> MessageSendEventsProvider for P2PGossipSync<G, C, L>
where
C::Target: chain::Access,
L::Target: Logger,
let (htlc_maximum_msat, effective_capacity) = match (htlc_maximum_msat, capacity_msat) {
(Some(amount_msat), Some(capacity_msat)) => {
let htlc_maximum_msat = cmp::min(amount_msat, capacity_msat);
- (htlc_maximum_msat, EffectiveCapacity::Total { capacity_msat })
+ (htlc_maximum_msat, EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat: Some(htlc_maximum_msat) })
},
(Some(amount_msat), None) => {
(amount_msat, EffectiveCapacity::MaximumHTLC { amount_msat })
},
(None, Some(capacity_msat)) => {
- (capacity_msat, EffectiveCapacity::Total { capacity_msat })
+ (capacity_msat, EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat: None })
},
(None, None) => (EffectiveCapacity::Unknown.as_msat(), EffectiveCapacity::Unknown),
};
/// Returns the [`EffectiveCapacity`] of the channel in the direction.
#[inline]
pub(super) fn effective_capacity(&self) -> EffectiveCapacity { self.inner.effective_capacity() }
-
- /// Returns the maximum HTLC amount allowed over the channel in the direction.
- #[inline]
- pub(super) fn htlc_maximum_msat(&self) -> u64 { self.inner.htlc_maximum_msat() }
}
impl<'a> fmt::Debug for DirectedChannelInfoWithUpdate<'a> {
Total {
/// The funding amount denominated in millisatoshi.
capacity_msat: u64,
+ /// The maximum HTLC amount denominated in millisatoshi.
+ htlc_maximum_msat: Option<u64>
},
/// A capacity sufficient to route any payment, typically used for private channels provided by
/// an invoice.
match self {
EffectiveCapacity::ExactLiquidity { liquidity_msat } => *liquidity_msat,
EffectiveCapacity::MaximumHTLC { amount_msat } => *amount_msat,
- EffectiveCapacity::Total { capacity_msat } => *capacity_msat,
+ EffectiveCapacity::Total { capacity_msat, .. } => *capacity_msat,
EffectiveCapacity::Infinite => u64::max_value(),
EffectiveCapacity::Unknown => UNKNOWN_CHANNEL_CAPACITY_MSAT,
}
/// Moniker assigned to the node.
/// May be invalid or malicious (eg control chars),
/// should not be exposed to the user.
- pub alias: [u8; 32],
+ pub alias: NodeAlias,
/// Internet-level addresses via which one can connect to the node
pub addresses: Vec<NetAddress>,
/// An initial announcement of the node
(10, addresses, vec_type),
});
+/// A user-defined name for a node, which may be used when displaying the node in a graph.
+///
+/// Since node aliases are provided by third parties, they are a potential avenue for injection
+/// attacks. Care must be taken when processing.
+#[derive(Clone, Debug, PartialEq)]
+pub struct NodeAlias(pub [u8; 32]);
+
+impl fmt::Display for NodeAlias {
+ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ let control_symbol = core::char::REPLACEMENT_CHARACTER;
+ let first_null = self.0.iter().position(|b| *b == 0).unwrap_or(self.0.len());
+ let bytes = self.0.split_at(first_null).0;
+ match core::str::from_utf8(bytes) {
+ Ok(alias) => {
+ for c in alias.chars() {
+ let mut bytes = [0u8; 4];
+ let c = if !c.is_control() { c } else { control_symbol };
+ f.write_str(c.encode_utf8(&mut bytes))?;
+ }
+ },
+ Err(_) => {
+ for c in bytes.iter().map(|b| *b as char) {
+ // Display printable ASCII characters
+ let mut bytes = [0u8; 4];
+ let c = if c >= '\x20' && c <= '\x7e' { c } else { control_symbol };
+ f.write_str(c.encode_utf8(&mut bytes))?;
+ }
+ },
+ };
+ Ok(())
+ }
+}
+
+impl Writeable for NodeAlias {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+ self.0.write(w)
+ }
+}
+
+impl Readable for NodeAlias {
+ fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
+ Ok(NodeAlias(Readable::read(r)?))
+ }
+}
+
#[derive(Clone, Debug, PartialEq)]
/// Details about a node in the network, known from the network announcement.
pub struct NodeInfo {
const SERIALIZATION_VERSION: u8 = 1;
const MIN_SERIALIZATION_VERSION: u8 = 1;
-impl Writeable for NetworkGraph {
+impl<L: Deref> Writeable for NetworkGraph<L> where L::Target: Logger {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
}
}
-impl Readable for NetworkGraph {
- fn read<R: io::Read>(reader: &mut R) -> Result<NetworkGraph, DecodeError> {
+impl<L: Deref> ReadableArgs<L> for NetworkGraph<L> where L::Target: Logger {
+ fn read<R: io::Read>(reader: &mut R, logger: L) -> Result<NetworkGraph<L>, DecodeError> {
let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
let genesis_hash: BlockHash = Readable::read(reader)?;
});
Ok(NetworkGraph {
+ secp_ctx: Secp256k1::verification_only(),
genesis_hash,
+ logger,
channels: RwLock::new(channels),
nodes: RwLock::new(nodes),
last_rapid_gossip_sync_timestamp: Mutex::new(last_rapid_gossip_sync_timestamp),
}
}
-impl fmt::Display for NetworkGraph {
+impl<L: Deref> fmt::Display for NetworkGraph<L> where L::Target: Logger {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
writeln!(f, "Network map\n[Channels]")?;
for (key, val) in self.channels.read().unwrap().iter() {
}
}
-impl PartialEq for NetworkGraph {
+impl<L: Deref> PartialEq for NetworkGraph<L> where L::Target: Logger {
fn eq(&self, other: &Self) -> bool {
self.genesis_hash == other.genesis_hash &&
*self.channels.read().unwrap() == *other.channels.read().unwrap() &&
}
}
-impl NetworkGraph {
+impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
/// Creates a new, empty, network graph.
- pub fn new(genesis_hash: BlockHash) -> NetworkGraph {
+ pub fn new(genesis_hash: BlockHash, logger: L) -> NetworkGraph<L> {
Self {
+ secp_ctx: Secp256k1::verification_only(),
genesis_hash,
+ logger,
channels: RwLock::new(BTreeMap::new()),
nodes: RwLock::new(BTreeMap::new()),
last_rapid_gossip_sync_timestamp: Mutex::new(None),
/// You probably don't want to call this directly, instead relying on a P2PGossipSync's
/// 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<T: secp256k1::Verification>(&self, msg: &msgs::NodeAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<(), LightningError> {
+ 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!(secp_ctx, &msg_hash, &msg.signature, &msg.contents.node_id, "node_announcement");
+ secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.signature, &msg.contents.node_id, "node_announcement");
self.update_node_from_announcement_intern(&msg.contents, Some(&msg))
}
features: msg.features.clone(),
last_update: msg.timestamp,
rgb: msg.rgb,
- alias: msg.alias,
+ alias: NodeAlias(msg.alias),
addresses: msg.addresses.clone(),
announcement_message: if should_relay { full_msg.cloned() } else { None },
});
///
/// If a `chain::Access` object is provided via `chain_access`, it will be called to verify
/// the corresponding UTXO exists on chain and is correctly-formatted.
- pub fn update_channel_from_announcement<T: secp256k1::Verification, C: Deref>(
- &self, msg: &msgs::ChannelAnnouncement, chain_access: &Option<C>, secp_ctx: &Secp256k1<T>
+ pub fn update_channel_from_announcement<C: Deref>(
+ &self, msg: &msgs::ChannelAnnouncement, chain_access: &Option<C>,
) -> Result<(), LightningError>
where
C::Target: chain::Access,
{
let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]);
- secp_verify_sig!(secp_ctx, &msg_hash, &msg.node_signature_1, &msg.contents.node_id_1, "channel_announcement");
- secp_verify_sig!(secp_ctx, &msg_hash, &msg.node_signature_2, &msg.contents.node_id_2, "channel_announcement");
- secp_verify_sig!(secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1, "channel_announcement");
- secp_verify_sig!(secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2, "channel_announcement");
+ secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_1, &msg.contents.node_id_1, "channel_announcement");
+ secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_2, &msg.contents.node_id_2, "channel_announcement");
+ secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1, "channel_announcement");
+ secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2, "channel_announcement");
self.update_channel_from_unsigned_announcement_intern(&msg.contents, Some(msg), chain_access)
}
///
/// If built with `no-std`, any updates with a timestamp more than two weeks in the past or
/// materially in the future will be rejected.
- pub fn update_channel<T: secp256k1::Verification>(&self, msg: &msgs::ChannelUpdate, secp_ctx: &Secp256k1<T>) -> Result<(), LightningError> {
- self.update_channel_intern(&msg.contents, Some(&msg), Some((&msg.signature, secp_ctx)))
+ pub fn update_channel(&self, msg: &msgs::ChannelUpdate) -> Result<(), LightningError> {
+ self.update_channel_intern(&msg.contents, Some(&msg), Some(&msg.signature))
}
/// For an already known (from announcement) channel, update info about one of the directions
/// If built with `no-std`, any updates with a timestamp more than two weeks in the past or
/// materially in the future will be rejected.
pub fn update_channel_unsigned(&self, msg: &msgs::UnsignedChannelUpdate) -> Result<(), LightningError> {
- self.update_channel_intern(msg, None, None::<(&secp256k1::ecdsa::Signature, &Secp256k1<secp256k1::VerifyOnly>)>)
+ self.update_channel_intern(msg, None, None)
}
- fn update_channel_intern<T: secp256k1::Verification>(&self, msg: &msgs::UnsignedChannelUpdate, full_msg: Option<&msgs::ChannelUpdate>, sig_info: Option<(&secp256k1::ecdsa::Signature, &Secp256k1<T>)>) -> Result<(), LightningError> {
+ fn update_channel_intern(&self, msg: &msgs::UnsignedChannelUpdate, full_msg: Option<&msgs::ChannelUpdate>, sig: Option<&secp256k1::ecdsa::Signature>) -> Result<(), LightningError> {
let dest_node_id;
let chan_enabled = msg.flags & (1 << 1) != (1 << 1);
let chan_was_enabled;
if msg.flags & 1 == 1 {
dest_node_id = channel.node_one.clone();
check_update_latest!(channel.two_to_one);
- if let Some((sig, ctx)) = sig_info {
- secp_verify_sig!(ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_two.as_slice()).map_err(|_| LightningError{
+ if let Some(sig) = sig {
+ secp_verify_sig!(self.secp_ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_two.as_slice()).map_err(|_| LightningError{
err: "Couldn't parse source node pubkey".to_owned(),
action: ErrorAction::IgnoreAndLog(Level::Debug)
})?, "channel_update");
} else {
dest_node_id = channel.node_two.clone();
check_update_latest!(channel.one_to_two);
- if let Some((sig, ctx)) = sig_info {
- secp_verify_sig!(ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_one.as_slice()).map_err(|_| LightningError{
+ if let Some(sig) = sig {
+ secp_verify_sig!(self.secp_ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_one.as_slice()).map_err(|_| LightningError{
err: "Couldn't parse destination node pubkey".to_owned(),
action: ErrorAction::IgnoreAndLog(Level::Debug)
})?, "channel_update");
&*self.channels
}
+ /// Returns information on a channel with the given id.
+ pub fn channel(&self, short_channel_id: u64) -> Option<&ChannelInfo> {
+ self.channels.get(&short_channel_id)
+ }
+
/// Returns all known nodes' public keys along with announced node info.
///
/// (C-not exported) because we have no mapping for `BTreeMap`s
&*self.nodes
}
+ /// Returns information on a node with the given id.
+ pub fn node(&self, node_id: &NodeId) -> Option<&NodeInfo> {
+ self.nodes.get(node_id)
+ }
+
/// 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.
use chain;
use ln::PaymentHash;
use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
- use routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate, MAX_EXCESS_BYTES_FOR_RELAY};
+ use routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate, NodeAlias, MAX_EXCESS_BYTES_FOR_RELAY};
use ln::msgs::{Init, OptionalField, RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
UnsignedChannelAnnouncement, ChannelAnnouncement, UnsignedChannelUpdate, ChannelUpdate,
ReplyChannelRange, QueryChannelRange, QueryShortChannelIds, MAX_VALUE_MSAT};
use util::test_utils;
- use util::logger::Logger;
- use util::ser::{Readable, Writeable};
+ use util::ser::{ReadableArgs, Writeable};
use util::events::{Event, EventHandler, MessageSendEvent, MessageSendEventsProvider};
use util::scid_utils::scid_from_parts;
use prelude::*;
use sync::Arc;
- fn create_network_graph() -> NetworkGraph {
+ fn create_network_graph() -> NetworkGraph<Arc<test_utils::TestLogger>> {
let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
- NetworkGraph::new(genesis_hash)
+ let logger = Arc::new(test_utils::TestLogger::new());
+ NetworkGraph::new(genesis_hash, logger)
}
- fn create_gossip_sync(network_graph: &NetworkGraph) -> (
- Secp256k1<All>, P2PGossipSync<&NetworkGraph, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>
+ fn create_gossip_sync(network_graph: &NetworkGraph<Arc<test_utils::TestLogger>>) -> (
+ Secp256k1<All>, P2PGossipSync<&NetworkGraph<Arc<test_utils::TestLogger>>,
+ Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>
) {
let secp_ctx = Secp256k1::new();
let logger = Arc::new(test_utils::TestLogger::new());
#[test]
fn handling_channel_announcements() {
let secp_ctx = Secp256k1::new();
- let logger: Arc<Logger> = Arc::new(test_utils::TestLogger::new());
+ let logger = test_utils::TestLogger::new();
let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
let valid_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx);
// Test if the UTXO lookups were not supported
- let network_graph = NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash());
- let mut gossip_sync = P2PGossipSync::new(&network_graph, None, Arc::clone(&logger));
+ let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
+ let network_graph = NetworkGraph::new(genesis_hash, &logger);
+ let mut gossip_sync = P2PGossipSync::new(&network_graph, None, &logger);
match gossip_sync.handle_channel_announcement(&valid_announcement) {
Ok(res) => assert!(res),
_ => panic!()
};
// Test if an associated transaction were not on-chain (or not confirmed).
- let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Testnet));
+ let chain_source = test_utils::TestChainSource::new(Network::Testnet);
*chain_source.utxo_ret.lock().unwrap() = Err(chain::AccessError::UnknownTx);
- let network_graph = NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash());
- gossip_sync = P2PGossipSync::new(&network_graph, Some(chain_source.clone()), Arc::clone(&logger));
+ let network_graph = NetworkGraph::new(genesis_hash, &logger);
+ gossip_sync = P2PGossipSync::new(&network_graph, Some(&chain_source), &logger);
let valid_announcement = get_signed_channel_announcement(|unsigned_announcement| {
unsigned_announcement.short_channel_id += 1;
#[test]
fn handling_channel_update() {
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 network_graph = NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash());
- let gossip_sync = P2PGossipSync::new(&network_graph, Some(chain_source.clone()), Arc::clone(&logger));
+ let logger = test_utils::TestLogger::new();
+ let chain_source = test_utils::TestChainSource::new(Network::Testnet);
+ let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
+ let network_graph = NetworkGraph::new(genesis_hash, &logger);
+ let gossip_sync = P2PGossipSync::new(&network_graph, Some(&chain_source), &logger);
let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
#[test]
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 gossip_sync = P2PGossipSync::new(&network_graph, Some(chain_source.clone()), &logger);
+ let network_graph = NetworkGraph::new(genesis_hash, &logger);
let secp_ctx = Secp256k1::new();
let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
let valid_channel_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx);
short_channel_id = valid_channel_announcement.contents.short_channel_id;
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.update_channel_from_announcement(&valid_channel_announcement, &chain_source).is_ok());
assert!(network_graph.read_only().channels().get(&short_channel_id).is_some());
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());
- gossip_sync.handle_event(&Event::PaymentPathFailed {
+ network_graph.handle_event(&Event::PaymentPathFailed {
payment_id: None,
payment_hash: PaymentHash([0; 32]),
rejected_by_dest: false,
}
};
- gossip_sync.handle_event(&Event::PaymentPathFailed {
+ network_graph.handle_event(&Event::PaymentPathFailed {
payment_id: None,
payment_hash: PaymentHash([0; 32]),
rejected_by_dest: false,
}
// Permanent closing deletes a channel
- gossip_sync.handle_event(&Event::PaymentPathFailed {
+ network_graph.handle_event(&Event::PaymentPathFailed {
payment_id: None,
payment_hash: PaymentHash([0; 32]),
rejected_by_dest: false,
fn test_channel_timeouts() {
// Test the removal of channels with `remove_stale_channels`.
let logger = test_utils::TestLogger::new();
- let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Testnet));
+ let chain_source = test_utils::TestChainSource::new(Network::Testnet);
let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
- let network_graph = NetworkGraph::new(genesis_hash);
- let gossip_sync = P2PGossipSync::new(&network_graph, Some(chain_source.clone()), &logger);
+ let network_graph = NetworkGraph::new(genesis_hash, &logger);
+ let gossip_sync = P2PGossipSync::new(&network_graph, Some(&chain_source), &logger);
let secp_ctx = Secp256k1::new();
let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
let valid_channel_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx);
let short_channel_id = valid_channel_announcement.contents.short_channel_id;
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.update_channel_from_announcement(&valid_channel_announcement, &chain_source).is_ok());
assert!(network_graph.read_only().channels().get(&short_channel_id).is_some());
let valid_channel_update = get_signed_channel_update(|_| {}, node_1_privkey, &secp_ctx);
assert!(!network_graph.read_only().nodes().is_empty());
assert!(!network_graph.read_only().channels().is_empty());
network_graph.write(&mut w).unwrap();
- assert!(<NetworkGraph>::read(&mut io::Cursor::new(&w.0)).unwrap() == network_graph);
+
+ let logger = Arc::new(test_utils::TestLogger::new());
+ assert!(<NetworkGraph<_>>::read(&mut io::Cursor::new(&w.0), logger).unwrap() == network_graph);
}
#[test]
let mut w = test_utils::TestVecWriter(Vec::new());
network_graph.write(&mut w).unwrap();
- let reassembled_network_graph: NetworkGraph = Readable::read(&mut io::Cursor::new(&w.0)).unwrap();
+
+ let logger = Arc::new(test_utils::TestLogger::new());
+ let reassembled_network_graph: NetworkGraph<_> = ReadableArgs::read(&mut io::Cursor::new(&w.0), logger).unwrap();
assert!(reassembled_network_graph == network_graph);
assert_eq!(reassembled_network_graph.get_last_rapid_gossip_sync_timestamp().unwrap(), 42);
}
}
fn do_handling_query_channel_range(
- gossip_sync: &P2PGossipSync<&NetworkGraph, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>,
+ gossip_sync: &P2PGossipSync<&NetworkGraph<Arc<test_utils::TestLogger>>, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>,
test_node_id: &PublicKey,
msg: QueryChannelRange,
expected_ok: bool,
});
assert!(result.is_err());
}
+
+ #[test]
+ fn displays_node_alias() {
+ let format_str_alias = |alias: &str| {
+ let mut bytes = [0u8; 32];
+ bytes[..alias.as_bytes().len()].copy_from_slice(alias.as_bytes());
+ format!("{}", NodeAlias(bytes))
+ };
+
+ assert_eq!(format_str_alias("I\u{1F496}LDK! \u{26A1}"), "I\u{1F496}LDK! \u{26A1}");
+ assert_eq!(format_str_alias("I\u{1F496}LDK!\0\u{26A1}"), "I\u{1F496}LDK!");
+ assert_eq!(format_str_alias("I\u{1F496}LDK!\t\u{26A1}"), "I\u{1F496}LDK!\u{FFFD}\u{26A1}");
+
+ let format_bytes_alias = |alias: &[u8]| {
+ let mut bytes = [0u8; 32];
+ bytes[..alias.len()].copy_from_slice(alias);
+ format!("{}", NodeAlias(bytes))
+ };
+
+ assert_eq!(format_bytes_alias(b"\xFFI <heart> LDK!"), "\u{FFFD}I <heart> LDK!");
+ assert_eq!(format_bytes_alias(b"\xFFI <heart>\0LDK!"), "\u{FFFD}I <heart>");
+ assert_eq!(format_bytes_alias(b"\xFFI <heart>\tLDK!"), "\u{FFFD}I <heart>\u{FFFD}LDK!");
+ }
}
#[cfg(all(test, feature = "_bench_unstable"))]
#[bench]
fn read_network_graph(bench: &mut Bencher) {
+ let logger = ::util::test_utils::TestLogger::new();
let mut d = ::routing::router::test_utils::get_route_file().unwrap();
let mut v = Vec::new();
d.read_to_end(&mut v).unwrap();
bench.iter(|| {
- let _ = NetworkGraph::read(&mut std::io::Cursor::new(&v)).unwrap();
+ let _ = NetworkGraph::read(&mut std::io::Cursor::new(&v), &logger).unwrap();
});
}
#[bench]
fn write_network_graph(bench: &mut Bencher) {
+ let logger = ::util::test_utils::TestLogger::new();
let mut d = ::routing::router::test_utils::get_route_file().unwrap();
- let net_graph = NetworkGraph::read(&mut d).unwrap();
+ let net_graph = NetworkGraph::read(&mut d, &logger).unwrap();
bench.iter(|| {
let _ = net_graph.encode();
});