use crate::prelude::*;
use core::{cmp, fmt};
use core::convert::TryFrom;
-use crate::sync::{RwLock, RwLockReadGuard};
+use crate::sync::{RwLock, RwLockReadGuard, LockTestExt};
#[cfg(feature = "std")]
use core::sync::atomic::{AtomicUsize, Ordering};
use crate::sync::Mutex;
},
}
}
+
+ /// Gets the genesis hash for this network graph.
+ pub fn get_genesis_hash(&self) -> BlockHash {
+ self.genesis_hash
+ }
}
macro_rules! secp_verify_sig {
htlc_maximum_msat = cmp::min(htlc_maximum_msat, capacity_msat);
EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat: htlc_maximum_msat }
},
- None => EffectiveCapacity::MaximumHTLC { amount_msat: htlc_maximum_msat },
+ None => EffectiveCapacity::AdvertisedMaxHTLC { amount_msat: htlc_maximum_msat },
};
Self {
liquidity_msat: u64,
},
/// The maximum HTLC amount in one direction as advertised on the gossip network.
- MaximumHTLC {
+ AdvertisedMaxHTLC {
/// The maximum HTLC amount denominated in millisatoshi.
amount_msat: u64,
},
/// A capacity sufficient to route any payment, typically used for private channels provided by
/// an invoice.
Infinite,
+ /// The maximum HTLC amount as provided by an invoice route hint.
+ HintMaxHTLC {
+ /// The maximum HTLC amount denominated in millisatoshi.
+ amount_msat: u64,
+ },
/// A capacity that is unknown possibly because either the chain state is unavailable to know
/// the total capacity or the `htlc_maximum_msat` was not advertised on the gossip network.
Unknown,
pub fn as_msat(&self) -> u64 {
match self {
EffectiveCapacity::ExactLiquidity { liquidity_msat } => *liquidity_msat,
- EffectiveCapacity::MaximumHTLC { amount_msat } => *amount_msat,
+ EffectiveCapacity::AdvertisedMaxHTLC { amount_msat } => *amount_msat,
EffectiveCapacity::Total { capacity_msat, .. } => *capacity_msat,
+ EffectiveCapacity::HintMaxHTLC { amount_msat } => *amount_msat,
EffectiveCapacity::Infinite => u64::max_value(),
EffectiveCapacity::Unknown => UNKNOWN_CHANNEL_CAPACITY_MSAT,
}
impl<L: Deref> Eq for NetworkGraph<L> where L::Target: Logger {}
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() &&
- *self.nodes.read().unwrap() == *other.nodes.read().unwrap()
+ // For a total lockorder, sort by position in memory and take the inner locks in that order.
+ // (Assumes that we can't move within memory while a lock is held).
+ let ord = ((self as *const _) as usize) < ((other as *const _) as usize);
+ let a = if ord { (&self.channels, &self.nodes) } else { (&other.channels, &other.nodes) };
+ let b = if ord { (&other.channels, &other.nodes) } else { (&self.channels, &self.nodes) };
+ let (channels_a, channels_b) = (a.0.unsafe_well_ordered_double_lock_self(), b.0.unsafe_well_ordered_double_lock_self());
+ let (nodes_a, nodes_b) = (a.1.unsafe_well_ordered_double_lock_self(), b.1.unsafe_well_ordered_double_lock_self());
+ self.genesis_hash.eq(&other.genesis_hash) && channels_a.eq(&channels_b) && nodes_a.eq(&nodes_b)
}
}
if msg.chain_hash != self.genesis_hash {
return Err(LightningError {
- err: "Channel announcement chain hash does not match genesis hash".to_owned(),
+ err: "Channel announcement chain hash does not match genesis hash".to_owned(),
action: ErrorAction::IgnoreAndLog(Level::Debug),
});
}
// It should ignore if gossip_queries feature is not enabled
{
- let init_msg = Init { features: InitFeatures::empty(), remote_network_address: None };
+ let init_msg = Init { features: InitFeatures::empty(), networks: None, remote_network_address: None };
gossip_sync.peer_connected(&node_id_1, &init_msg, true).unwrap();
let events = gossip_sync.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 0);
{
let mut features = InitFeatures::empty();
features.set_gossip_queries_optional();
- let init_msg = Init { features, remote_network_address: None };
+ let init_msg = Init { features, networks: None, remote_network_address: None };
gossip_sync.peer_connected(&node_id_1, &init_msg, true).unwrap();
let events = gossip_sync.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);