Skip to content

Commit 92afa3d

Browse files
committed
Add a read-only view of NetworkGraph
Hide the internal locking of NetworkGraph by providing a read-only view. This way the locking order is handled internally.
1 parent a1b4fb0 commit 92afa3d

File tree

2 files changed

+70
-49
lines changed

2 files changed

+70
-49
lines changed

lightning/src/routing/network_graph.rs

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ pub struct NetworkGraph {
5858
nodes: RwLock<BTreeMap<PublicKey, NodeInfo>>,
5959
}
6060

61+
/// A read-only view of [`NetworkGraph`].
62+
pub struct ReadOnlyNetworkGraph<'a> {
63+
channels: RwLockReadGuard<'a, BTreeMap<u64, ChannelInfo>>,
64+
nodes: RwLockReadGuard<'a, BTreeMap<PublicKey, NodeInfo>>,
65+
}
66+
6167
/// Receives and validates network updates from peers,
6268
/// stores authentic and relevant data as a network graph.
6369
/// This network graph is then used for routing payments.
@@ -171,8 +177,8 @@ impl<C: Deref , L: Deref > RoutingMessageHandler for NetGraphMsgHandler<C, L> wh
171177

172178
fn get_next_channel_announcements(&self, starting_point: u64, batch_amount: u8) -> Vec<(ChannelAnnouncement, Option<ChannelUpdate>, Option<ChannelUpdate>)> {
173179
let mut result = Vec::with_capacity(batch_amount as usize);
174-
let channels = self.network_graph.get_channels();
175-
let mut iter = channels.range(starting_point..);
180+
let network_graph = self.network_graph.read_only();
181+
let mut iter = network_graph.channels().range(starting_point..);
176182
while result.len() < batch_amount as usize {
177183
if let Some((_, ref chan)) = iter.next() {
178184
if chan.announcement_message.is_some() {
@@ -199,7 +205,8 @@ impl<C: Deref , L: Deref > RoutingMessageHandler for NetGraphMsgHandler<C, L> wh
199205

200206
fn get_next_node_announcements(&self, starting_point: Option<&PublicKey>, batch_amount: u8) -> Vec<NodeAnnouncement> {
201207
let mut result = Vec::with_capacity(batch_amount as usize);
202-
let nodes = self.network_graph.get_nodes();
208+
let network_graph = self.network_graph.read_only();
209+
let nodes = network_graph.nodes();
203210
let mut iter = if let Some(pubkey) = starting_point {
204211
let mut iter = nodes.range((*pubkey)..);
205212
iter.next();
@@ -340,7 +347,8 @@ impl<C: Deref , L: Deref > RoutingMessageHandler for NetGraphMsgHandler<C, L> wh
340347
// (has at least one update). A peer may still want to know the channel
341348
// exists even if its not yet routable.
342349
let mut batches: Vec<Vec<u64>> = vec![Vec::with_capacity(MAX_SCIDS_PER_REPLY)];
343-
for (_, ref chan) in self.network_graph.get_channels().range(inclusive_start_scid.unwrap()..exclusive_end_scid.unwrap()) {
350+
let network_graph = self.network_graph.read_only();
351+
for (_, ref chan) in network_graph.channels().range(inclusive_start_scid.unwrap()..exclusive_end_scid.unwrap()) {
344352
if let Some(chan_announcement) = &chan.announcement_message {
345353
// Construct a new batch if last one is full
346354
if batches.last().unwrap().len() == batches.last().unwrap().capacity() {
@@ -662,34 +670,6 @@ impl PartialEq for NetworkGraph {
662670
}
663671

664672
impl NetworkGraph {
665-
/// Returns all known valid channels' short ids along with announced channel info.
666-
///
667-
/// (C-not exported) because we have no mapping for `BTreeMap`s
668-
pub fn get_channels(&self) -> RwLockReadGuard<'_, BTreeMap<u64, ChannelInfo>> {
669-
self.channels.read().unwrap()
670-
}
671-
672-
/// Returns all known nodes' public keys along with announced node info.
673-
///
674-
/// (C-not exported) because we have no mapping for `BTreeMap`s
675-
pub fn get_nodes(&self) -> RwLockReadGuard<'_, BTreeMap<PublicKey, NodeInfo>> {
676-
self.nodes.read().unwrap()
677-
}
678-
679-
/// Get network addresses by node id.
680-
/// Returns None if the requested node is completely unknown,
681-
/// or if node announcement for the node was never received.
682-
///
683-
/// (C-not exported) as there is no practical way to track lifetimes of returned values.
684-
pub fn get_addresses(&self, pubkey: &PublicKey) -> Option<Vec<NetAddress>> {
685-
if let Some(node) = self.nodes.read().unwrap().get(pubkey) {
686-
if let Some(node_info) = node.announcement_info.as_ref() {
687-
return Some(node_info.addresses.clone())
688-
}
689-
}
690-
None
691-
}
692-
693673
/// Creates a new, empty, network graph.
694674
pub fn new(genesis_hash: BlockHash) -> NetworkGraph {
695675
Self {
@@ -699,6 +679,16 @@ impl NetworkGraph {
699679
}
700680
}
701681

682+
/// Returns a read-only view of the network graph.
683+
pub fn read_only(&'_ self) -> ReadOnlyNetworkGraph<'_> {
684+
let channels = self.channels.read().unwrap();
685+
let nodes = self.nodes.read().unwrap();
686+
ReadOnlyNetworkGraph {
687+
channels,
688+
nodes,
689+
}
690+
}
691+
702692
/// For an already known node (from channel announcements), update its stored properties from a
703693
/// given node announcement.
704694
///
@@ -1064,6 +1054,36 @@ impl NetworkGraph {
10641054
}
10651055
}
10661056

1057+
impl ReadOnlyNetworkGraph<'_> {
1058+
/// Returns all known valid channels' short ids along with announced channel info.
1059+
///
1060+
/// (C-not exported) because we have no mapping for `BTreeMap`s
1061+
pub fn channels(&self) -> &BTreeMap<u64, ChannelInfo> {
1062+
&*self.channels
1063+
}
1064+
1065+
/// Returns all known nodes' public keys along with announced node info.
1066+
///
1067+
/// (C-not exported) because we have no mapping for `BTreeMap`s
1068+
pub fn nodes(&self) -> &BTreeMap<PublicKey, NodeInfo> {
1069+
&*self.nodes
1070+
}
1071+
1072+
/// Get network addresses by node id.
1073+
/// Returns None if the requested node is completely unknown,
1074+
/// or if node announcement for the node was never received.
1075+
///
1076+
/// (C-not exported) as there is no practical way to track lifetimes of returned values.
1077+
pub fn get_addresses(&self, pubkey: &PublicKey) -> Option<&Vec<NetAddress>> {
1078+
if let Some(node) = self.nodes.get(pubkey) {
1079+
if let Some(node_info) = node.announcement_info.as_ref() {
1080+
return Some(&node_info.addresses)
1081+
}
1082+
}
1083+
None
1084+
}
1085+
}
1086+
10671087
#[cfg(test)]
10681088
mod tests {
10691089
use chain;
@@ -1268,7 +1288,7 @@ mod tests {
12681288

12691289
{
12701290
let network = &net_graph_msg_handler.network_graph;
1271-
match network.get_channels().get(&unsigned_announcement.short_channel_id) {
1291+
match network.read_only().channels().get(&unsigned_announcement.short_channel_id) {
12721292
None => panic!(),
12731293
Some(_) => ()
12741294
};
@@ -1320,7 +1340,7 @@ mod tests {
13201340

13211341
{
13221342
let network = &net_graph_msg_handler.network_graph;
1323-
match network.get_channels().get(&unsigned_announcement.short_channel_id) {
1343+
match network.read_only().channels().get(&unsigned_announcement.short_channel_id) {
13241344
None => panic!(),
13251345
Some(_) => ()
13261346
};
@@ -1351,7 +1371,7 @@ mod tests {
13511371
};
13521372
{
13531373
let network = &net_graph_msg_handler.network_graph;
1354-
match network.get_channels().get(&unsigned_announcement.short_channel_id) {
1374+
match network.read_only().channels().get(&unsigned_announcement.short_channel_id) {
13551375
Some(channel_entry) => {
13561376
assert_eq!(channel_entry.features, ChannelFeatures::empty());
13571377
},
@@ -1481,7 +1501,7 @@ mod tests {
14811501

14821502
{
14831503
let network = &net_graph_msg_handler.network_graph;
1484-
match network.get_channels().get(&short_channel_id) {
1504+
match network.read_only().channels().get(&short_channel_id) {
14851505
None => panic!(),
14861506
Some(channel_info) => {
14871507
assert_eq!(channel_info.one_to_two.as_ref().unwrap().cltv_expiry_delta, 144);
@@ -1587,7 +1607,7 @@ mod tests {
15871607
{
15881608
// There is no nodes in the table at the beginning.
15891609
let network = &net_graph_msg_handler.network_graph;
1590-
assert_eq!(network.get_nodes().len(), 0);
1610+
assert_eq!(network.read_only().nodes().len(), 0);
15911611
}
15921612

15931613
{
@@ -1643,7 +1663,7 @@ mod tests {
16431663
// Non-permanent closing just disables a channel
16441664
{
16451665
let network = &net_graph_msg_handler.network_graph;
1646-
match network.get_channels().get(&short_channel_id) {
1666+
match network.read_only().channels().get(&short_channel_id) {
16471667
None => panic!(),
16481668
Some(channel_info) => {
16491669
assert!(channel_info.one_to_two.is_some());
@@ -1661,7 +1681,7 @@ mod tests {
16611681
// Non-permanent closing just disables a channel
16621682
{
16631683
let network = &net_graph_msg_handler.network_graph;
1664-
match network.get_channels().get(&short_channel_id) {
1684+
match network.read_only().channels().get(&short_channel_id) {
16651685
None => panic!(),
16661686
Some(channel_info) => {
16671687
assert!(!channel_info.one_to_two.as_ref().unwrap().enabled);
@@ -1679,9 +1699,9 @@ mod tests {
16791699
// Permanent closing deletes a channel
16801700
{
16811701
let network = &net_graph_msg_handler.network_graph;
1682-
assert_eq!(network.get_channels().len(), 0);
1702+
assert_eq!(network.read_only().channels().len(), 0);
16831703
// Nodes are also deleted because there are no associated channels anymore
1684-
assert_eq!(network.get_nodes().len(), 0);
1704+
assert_eq!(network.read_only().nodes().len(), 0);
16851705
}
16861706
// TODO: Test HTLCFailChannelUpdate::NodeFailure, which is not implemented yet.
16871707
}
@@ -1998,8 +2018,8 @@ mod tests {
19982018

19992019
let network = &net_graph_msg_handler.network_graph;
20002020
let mut w = test_utils::TestVecWriter(Vec::new());
2001-
assert!(!network.get_nodes().is_empty());
2002-
assert!(!network.get_channels().is_empty());
2021+
assert!(!network.read_only().nodes().is_empty());
2022+
assert!(!network.read_only().channels().is_empty());
20032023
network.write(&mut w).unwrap();
20042024
assert!(<NetworkGraph>::read(&mut io::Cursor::new(&w.0)).unwrap() == *network);
20052025
}

lightning/src/routing/router.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,9 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, paye
442442
// to use as the A* heuristic beyond just the cost to get one node further than the current
443443
// one.
444444

445-
let network_channels = network.get_channels();
446-
let network_nodes = network.get_nodes();
445+
let network_graph = network.read_only();
446+
let network_channels = network_graph.channels();
447+
let network_nodes = network_graph.nodes();
447448
let dummy_directional_info = DummyDirectionalChannelInfo { // used for first_hops routes
448449
cltv_expiry_delta: 0,
449450
htlc_minimum_msat: 0,
@@ -3858,7 +3859,7 @@ mod tests {
38583859

38593860
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
38603861
let mut seed = random_init_seed() as usize;
3861-
let nodes = graph.get_nodes();
3862+
let nodes = graph.read_only().nodes().clone();
38623863
'load_endpoints: for _ in 0..10 {
38633864
loop {
38643865
seed = seed.overflowing_mul(0xdeadbeef).0;
@@ -3887,7 +3888,7 @@ mod tests {
38873888

38883889
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
38893890
let mut seed = random_init_seed() as usize;
3890-
let nodes = graph.get_nodes();
3891+
let nodes = graph.read_only().nodes().clone();
38913892
'load_endpoints: for _ in 0..10 {
38923893
loop {
38933894
seed = seed.overflowing_mul(0xdeadbeef).0;
@@ -3946,7 +3947,7 @@ mod benches {
39463947
fn generate_routes(bench: &mut Bencher) {
39473948
let mut d = test_utils::get_route_file().unwrap();
39483949
let graph = NetworkGraph::read(&mut d).unwrap();
3949-
let nodes = graph.get_nodes();
3950+
let nodes = graph.read_only().nodes().clone();
39503951

39513952
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
39523953
let mut path_endpoints = Vec::new();
@@ -3978,7 +3979,7 @@ mod benches {
39783979
fn generate_mpp_routes(bench: &mut Bencher) {
39793980
let mut d = test_utils::get_route_file().unwrap();
39803981
let graph = NetworkGraph::read(&mut d).unwrap();
3981-
let nodes = graph.get_nodes();
3982+
let nodes = graph.read_only().nodes().clone();
39823983

39833984
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
39843985
let mut path_endpoints = Vec::new();

0 commit comments

Comments
 (0)