Skip to content

Commit 87a6e01

Browse files
committed
Have find_route take a NetworkGraph instead of a ReadOnly one
Because downstream languages are often garbage-collected, having the user directly allocate a `ReadOnlyNetworkGraph` and pass a reference to it to `find_route` often results in holding a read lock long in excess of the `find_route` call. Worse, some languages (like JavaScript) tend to only garbage collect when other code is not running, possibly leading to deadlocks.
1 parent a600eee commit 87a6e01

File tree

7 files changed

+29
-30
lines changed

7 files changed

+29
-30
lines changed

fuzz/src/full_stack.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
460460
final_cltv_expiry_delta: 42,
461461
};
462462
let random_seed_bytes: [u8; 32] = keys_manager.get_secure_random_bytes();
463-
let route = match find_route(&our_id, &params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &random_seed_bytes) {
463+
let route = match find_route(&our_id, &params, &network_graph, None, Arc::clone(&logger), &scorer, &random_seed_bytes) {
464464
Ok(route) => route,
465465
Err(_) => return,
466466
};
@@ -484,7 +484,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
484484
final_cltv_expiry_delta: 42,
485485
};
486486
let random_seed_bytes: [u8; 32] = keys_manager.get_secure_random_bytes();
487-
let mut route = match find_route(&our_id, &params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &random_seed_bytes) {
487+
let mut route = match find_route(&our_id, &params, &network_graph, None, Arc::clone(&logger), &scorer, &random_seed_bytes) {
488488
Ok(route) => route,
489489
Err(_) => return,
490490
};

fuzz/src/router.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
268268
final_value_msat: slice_to_be64(get_slice!(8)),
269269
final_cltv_expiry_delta: slice_to_be32(get_slice!(4)),
270270
};
271-
let _ = find_route(&our_pubkey, &route_params, &net_graph.read_only(),
271+
let _ = find_route(&our_pubkey, &route_params, &net_graph,
272272
first_hops.map(|c| c.iter().collect::<Vec<_>>()).as_ref().map(|a| a.as_slice()),
273273
&logger, &scorer, &random_seed_bytes);
274274
}

lightning-invoice/src/utils.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -461,13 +461,12 @@ where L::Target: Logger {
461461
&self, payer: &PublicKey, params: &RouteParameters, _payment_hash: &PaymentHash,
462462
first_hops: Option<&[&ChannelDetails]>, scorer: &S
463463
) -> Result<Route, LightningError> {
464-
let network_graph = self.network_graph.read_only();
465464
let random_seed_bytes = {
466465
let mut locked_random_seed_bytes = self.random_seed_bytes.lock().unwrap();
467466
*locked_random_seed_bytes = sha256::Hash::hash(&*locked_random_seed_bytes).into_inner();
468467
*locked_random_seed_bytes
469468
};
470-
find_route(payer, params, &network_graph, first_hops, &*self.logger, scorer, &random_seed_bytes)
469+
find_route(payer, params, &self.network_graph, first_hops, &*self.logger, scorer, &random_seed_bytes)
471470
}
472471
}
473472

@@ -572,7 +571,7 @@ mod test {
572571
let scorer = test_utils::TestScorer::with_penalty(0);
573572
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
574573
let route = find_route(
575-
&nodes[0].node.get_our_node_id(), &route_params, &network_graph.read_only(),
574+
&nodes[0].node.get_our_node_id(), &route_params, &network_graph,
576575
Some(&first_hops.iter().collect::<Vec<_>>()), &logger, &scorer, &random_seed_bytes
577576
).unwrap();
578577

@@ -848,7 +847,7 @@ mod test {
848847
let scorer = test_utils::TestScorer::with_penalty(0);
849848
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
850849
let route = find_route(
851-
&nodes[0].node.get_our_node_id(), &params, &network_graph.read_only(),
850+
&nodes[0].node.get_our_node_id(), &params, &network_graph,
852851
Some(&first_hops.iter().collect::<Vec<_>>()), &logger, &scorer, &random_seed_bytes
853852
).unwrap();
854853
let (payment_event, fwd_idx) = {

lightning/src/ln/channelmanager.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -7460,7 +7460,7 @@ mod tests {
74607460
final_cltv_expiry_delta: TEST_FINAL_CLTV,
74617461
};
74627462
let route = find_route(
7463-
&nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph.read_only(),
7463+
&nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph,
74647464
None, nodes[0].logger, &scorer, &random_seed_bytes
74657465
).unwrap();
74667466
nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap();
@@ -7491,7 +7491,7 @@ mod tests {
74917491
// To start (2), send a keysend payment but don't claim it.
74927492
let payment_preimage = PaymentPreimage([42; 32]);
74937493
let route = find_route(
7494-
&nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph.read_only(),
7494+
&nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph,
74957495
None, nodes[0].logger, &scorer, &random_seed_bytes
74967496
).unwrap();
74977497
let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap();
@@ -7555,9 +7555,8 @@ mod tests {
75557555
let scorer = test_utils::TestScorer::with_penalty(0);
75567556
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
75577557
let route = find_route(
7558-
&payer_pubkey, &route_params, &network_graph.read_only(),
7559-
Some(&first_hops.iter().collect::<Vec<_>>()), nodes[0].logger, &scorer,
7560-
&random_seed_bytes
7558+
&payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
7559+
nodes[0].logger, &scorer, &random_seed_bytes
75617560
).unwrap();
75627561

75637562
let test_preimage = PaymentPreimage([42; 32]);
@@ -7600,9 +7599,8 @@ mod tests {
76007599
let scorer = test_utils::TestScorer::with_penalty(0);
76017600
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
76027601
let route = find_route(
7603-
&payer_pubkey, &route_params, &network_graph.read_only(),
7604-
Some(&first_hops.iter().collect::<Vec<_>>()), nodes[0].logger, &scorer,
7605-
&random_seed_bytes
7602+
&payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
7603+
nodes[0].logger, &scorer, &random_seed_bytes
76067604
).unwrap();
76077605

76087606
let test_preimage = PaymentPreimage([42; 32]);

lightning/src/ln/functional_tests.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -9874,7 +9874,7 @@ fn test_keysend_payments_to_public_node() {
98749874
};
98759875
let scorer = test_utils::TestScorer::with_penalty(0);
98769876
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
9877-
let route = find_route(&payer_pubkey, &route_params, &network_graph.read_only(), None, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
9877+
let route = find_route(&payer_pubkey, &route_params, &network_graph, None, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
98789878

98799879
let test_preimage = PaymentPreimage([42; 32]);
98809880
let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage)).unwrap();
@@ -9910,8 +9910,8 @@ fn test_keysend_payments_to_private_node() {
99109910
let scorer = test_utils::TestScorer::with_penalty(0);
99119911
let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
99129912
let route = find_route(
9913-
&payer_pubkey, &route_params, &network_graph.read_only(),
9914-
Some(&first_hops.iter().collect::<Vec<_>>()), nodes[0].logger, &scorer, &random_seed_bytes
9913+
&payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
9914+
nodes[0].logger, &scorer, &random_seed_bytes
99159915
).unwrap();
99169916

99179917
let test_preimage = PaymentPreimage([42; 32]);

lightning/src/routing/router.rs

+13-11
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use bitcoin::secp256k1::PublicKey;
1717
use ln::channelmanager::ChannelDetails;
1818
use ln::features::{ChannelFeatures, InvoiceFeatures, NodeFeatures};
1919
use ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT};
20-
use routing::gossip::{DirectedChannelInfoWithUpdate, EffectiveCapacity, ReadOnlyNetworkGraph, NodeId, RoutingFees};
20+
use routing::gossip::{DirectedChannelInfoWithUpdate, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId, RoutingFees};
2121
use routing::scoring::{ChannelUsage, Score};
2222
use util::ser::{Writeable, Readable, Writer};
2323
use util::logger::{Level, Logger};
@@ -690,16 +690,17 @@ fn default_node_features() -> NodeFeatures {
690690
/// [`ChannelManager::list_usable_channels`]: crate::ln::channelmanager::ChannelManager::list_usable_channels
691691
/// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
692692
/// [`NetworkGraph`]: crate::routing::gossip::NetworkGraph
693-
pub fn find_route<L: Deref, S: Score>(
693+
pub fn find_route<L: Deref, GL: Deref, S: Score>(
694694
our_node_pubkey: &PublicKey, route_params: &RouteParameters,
695-
network_graph: &ReadOnlyNetworkGraph, first_hops: Option<&[&ChannelDetails]>, logger: L,
695+
network_graph: &NetworkGraph<GL>, first_hops: Option<&[&ChannelDetails]>, logger: L,
696696
scorer: &S, random_seed_bytes: &[u8; 32]
697697
) -> Result<Route, LightningError>
698-
where L::Target: Logger {
699-
let mut route = get_route(our_node_pubkey, &route_params.payment_params, network_graph, first_hops,
698+
where L::Target: Logger, GL::Target: Logger {
699+
let graph_lock = network_graph.read_only();
700+
let mut route = get_route(our_node_pubkey, &route_params.payment_params, &graph_lock, first_hops,
700701
route_params.final_value_msat, route_params.final_cltv_expiry_delta, logger, scorer,
701702
random_seed_bytes)?;
702-
add_random_cltv_offset(&mut route, &route_params.payment_params, network_graph, random_seed_bytes);
703+
add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes);
703704
Ok(route)
704705
}
705706

@@ -1803,15 +1804,16 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters,
18031804
/// exclude the payer, but include the payee). This may be useful, e.g., for probing the chosen path.
18041805
///
18051806
/// Re-uses logic from `find_route`, so the restrictions described there also apply here.
1806-
pub fn build_route_from_hops<L: Deref>(
1807+
pub fn build_route_from_hops<L: Deref, GL: Deref>(
18071808
our_node_pubkey: &PublicKey, hops: &[PublicKey], route_params: &RouteParameters,
1808-
network_graph: &ReadOnlyNetworkGraph, logger: L, random_seed_bytes: &[u8; 32]
1809+
network_graph: &NetworkGraph<GL>, logger: L, random_seed_bytes: &[u8; 32]
18091810
) -> Result<Route, LightningError>
1810-
where L::Target: Logger {
1811+
where L::Target: Logger, GL::Target: Logger {
1812+
let graph_lock = network_graph.read_only();
18111813
let mut route = build_route_from_hops_internal(
1812-
our_node_pubkey, hops, &route_params.payment_params, &network_graph,
1814+
our_node_pubkey, hops, &route_params.payment_params, &graph_lock,
18131815
route_params.final_value_msat, route_params.final_cltv_expiry_delta, logger, random_seed_bytes)?;
1814-
add_random_cltv_offset(&mut route, &route_params.payment_params, &network_graph, random_seed_bytes);
1816+
add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes);
18151817
Ok(route)
18161818
}
18171819

lightning/src/routing/scoring.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
//! let scorer = ProbabilisticScorer::new(params, &network_graph, &logger);
4444
//! # let random_seed_bytes = [42u8; 32];
4545
//!
46-
//! let route = find_route(&payer, &route_params, &network_graph.read_only(), None, &logger, &scorer, &random_seed_bytes);
46+
//! let route = find_route(&payer, &route_params, &network_graph, None, &logger, &scorer, &random_seed_bytes);
4747
//! # }
4848
//! ```
4949
//!

0 commit comments

Comments
 (0)