/// given path is variable, keeping the length of any path to less than 20 should currently
/// ensure it is viable.
pub paths: Vec<Vec<RouteHop>>,
+ /// The `payee` parameter passed to [`find_route`].
+ /// This is used by `ChannelManager` to track information which may be required for retries,
+ /// provided back to you via [`Event::PaymentPathFailed`].
+ ///
+ /// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
+ pub payee: Option<Payee>,
+}
+
+pub(crate) trait RoutePath {
+ /// Gets the fees for a given path, excluding any excess paid to the recipient.
+ fn get_path_fees(&self) -> u64;
+}
+impl RoutePath for Vec<RouteHop> {
+ fn get_path_fees(&self) -> u64 {
+ // Do not count last hop of each path since that's the full value of the payment
+ self.split_last().map(|(_, path_prefix)| path_prefix).unwrap_or(&[])
+ .iter().map(|hop| &hop.fee_msat)
+ .sum()
+ }
}
impl Route {
/// Returns the total amount of fees paid on this [`Route`].
///
/// This doesn't include any extra payment made to the recipient, which can happen in excess of
- /// the amount passed to [`get_route`]'s `final_value_msat`.
+ /// the amount passed to [`find_route`]'s `params.final_value_msat`.
pub fn get_total_fees(&self) -> u64 {
- // Do not count last hop of each path since that's the full value of the payment
- return self.paths.iter()
- .flat_map(|path| path.split_last().map(|(_, path_prefix)| path_prefix).unwrap_or(&[]))
- .map(|hop| &hop.fee_msat)
- .sum();
+ self.paths.iter().map(|path| path.get_path_fees()).sum()
}
/// Returns the total amount paid on this [`Route`], excluding the fees.
hop.write(writer)?;
}
}
- write_tlv_fields!(writer, {});
+ write_tlv_fields!(writer, {
+ (1, self.payee, option),
+ });
Ok(())
}
}
}
paths.push(hops);
}
- read_tlv_fields!(reader, {});
- Ok(Route { paths })
+ let mut payee = None;
+ read_tlv_fields!(reader, {
+ (1, payee, option),
+ });
+ Ok(Route { paths, payee })
}
}
+/// Parameters needed to find a [`Route`] for paying a [`Payee`].
+///
+/// Passed to [`find_route`] and also provided in [`Event::PaymentPathFailed`] for retrying a failed
+/// payment path.
+///
+/// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
+#[derive(Clone, Debug)]
+pub struct RouteParameters {
+ /// The recipient of the failed payment path.
+ pub payee: Payee,
+
+ /// The amount in msats sent on the failed payment path.
+ pub final_value_msat: u64,
+
+ /// The CLTV on the final hop of the failed payment path.
+ pub final_cltv_expiry_delta: u32,
+}
+
+impl_writeable_tlv_based!(RouteParameters, {
+ (0, payee, required),
+ (2, final_value_msat, required),
+ (4, final_cltv_expiry_delta, required),
+});
+
/// The recipient of a payment.
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Payee {
/// The node id of the payee.
- pubkey: PublicKey,
+ pub pubkey: PublicKey,
/// Features supported by the payee.
///
/// Hints for routing to the payee, containing channels connecting the payee to public nodes.
pub route_hints: Vec<RouteHint>,
+
+ /// Expiration of a payment to the payee, in seconds relative to the UNIX epoch.
+ pub expiry_time: Option<u64>,
}
+impl_writeable_tlv_based!(Payee, {
+ (0, pubkey, required),
+ (2, features, option),
+ (4, route_hints, vec_type),
+ (6, expiry_time, option),
+});
+
impl Payee {
/// Creates a payee with the node id of the given `pubkey`.
pub fn new(pubkey: PublicKey) -> Self {
pubkey,
features: None,
route_hints: vec![],
+ expiry_time: None,
}
}
pub fn with_route_hints(self, route_hints: Vec<RouteHint>) -> Self {
Self { route_hints, ..self }
}
+
+ /// Includes a payment expiration in seconds relative to the UNIX epoch.
+ pub fn with_expiry_time(self, expiry_time: u64) -> Self {
+ Self { expiry_time: Some(expiry_time), ..self }
+ }
}
/// A list of hops along a payment path terminating with a channel to the recipient.
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub struct RouteHint(pub Vec<RouteHintHop>);
+
+impl Writeable for RouteHint {
+ fn write<W: ::util::ser::Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+ (self.0.len() as u64).write(writer)?;
+ for hop in self.0.iter() {
+ hop.write(writer)?;
+ }
+ Ok(())
+ }
+}
+
+impl Readable for RouteHint {
+ fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+ let hop_count: u64 = Readable::read(reader)?;
+ let mut hops = Vec::with_capacity(cmp::min(hop_count, 16) as usize);
+ for _ in 0..hop_count {
+ hops.push(Readable::read(reader)?);
+ }
+ Ok(Self(hops))
+ }
+}
+
/// A channel descriptor for a hop along a payment path.
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub struct RouteHintHop {
pub htlc_maximum_msat: Option<u64>,
}
+impl_writeable_tlv_based!(RouteHintHop, {
+ (0, src_node_id, required),
+ (1, htlc_minimum_msat, option),
+ (2, short_channel_id, required),
+ (3, htlc_maximum_msat, option),
+ (4, fees, required),
+ (6, cltv_expiry_delta, required),
+});
+
#[derive(Eq, PartialEq)]
struct RouteGraphNode {
node_id: NodeId,
}
}
-/// Gets a keysend route from us (payer) to the given target node (payee). This is needed because
-/// keysend payments do not have an invoice from which to pull the payee's supported features, which
-/// makes it tricky to otherwise supply the `payee` parameter of `get_route`.
-pub fn get_keysend_route<L: Deref, S: routing::Score>(
- our_node_pubkey: &PublicKey, network: &NetworkGraph, payee: &PublicKey,
- first_hops: Option<&[&ChannelDetails]>, last_hops: &[&RouteHint], final_value_msat: u64,
- final_cltv: u32, logger: L, scorer: &S
+/// Finds a route from us (payer) to the given target node (payee).
+///
+/// If the payee provided features in their invoice, they should be provided via `params.payee`.
+/// Without this, MPP will only be used if the payee's features are available in the network graph.
+///
+/// Private routing paths between a public node and the target may be included in `params.payee`.
+///
+/// If some channels aren't announced, it may be useful to fill in `first_hops` with the results
+/// from [`ChannelManager::list_usable_channels`]. If it is filled in, the view of our local
+/// channels from [`NetworkGraph`] will be ignored, and only those in `first_hops` will be used.
+///
+/// The fees on channels from us to the next hop are ignored as they are assumed to all be equal.
+/// However, the enabled/disabled bit on such channels as well as the `htlc_minimum_msat` /
+/// `htlc_maximum_msat` *are* checked as they may change based on the receiving node.
+///
+/// # Note
+///
+/// May be used to re-compute a [`Route`] when handling a [`Event::PaymentPathFailed`]. Any
+/// adjustments to the [`NetworkGraph`] and channel scores should be made prior to calling this
+/// function.
+///
+/// # Panics
+///
+/// Panics if first_hops contains channels without short_channel_ids;
+/// [`ChannelManager::list_usable_channels`] will never include such channels.
+///
+/// [`ChannelManager::list_usable_channels`]: crate::ln::channelmanager::ChannelManager::list_usable_channels
+/// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
+pub fn find_route<L: Deref, S: routing::Score>(
+ our_node_pubkey: &PublicKey, params: &RouteParameters, network: &NetworkGraph,
+ first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S
) -> Result<Route, LightningError>
where L::Target: Logger {
- let route_hints = last_hops.iter().map(|hint| (*hint).clone()).collect();
- let payee = Payee::for_keysend(*payee).with_route_hints(route_hints);
get_route(
- our_node_pubkey, &payee, network, first_hops, final_value_msat, final_cltv, logger, scorer
+ our_node_pubkey, ¶ms.payee, network, first_hops, params.final_value_msat,
+ params.final_cltv_expiry_delta, logger, scorer
)
}
-/// Gets a route from us (payer) to the given target node (payee).
-///
-/// If the payee provided features in their invoice, they should be provided via `payee`. Without
-/// this, MPP will only be used if the payee's features are available in the network graph.
-///
-/// Private routing paths between a public node and the target may be included in `payee`.
-/// Currently, only the last hop in each path is considered.
-///
-/// If some channels aren't announced, it may be useful to fill in a first_hops with the
-/// results from a local ChannelManager::list_usable_channels() call. If it is filled in, our
-/// view of our local channels (from net_graph_msg_handler) will be ignored, and only those
-/// in first_hops will be used.
-///
-/// Panics if first_hops contains channels without short_channel_ids
-/// (ChannelManager::list_usable_channels will never include such channels).
-///
-/// The fees on channels from us to next-hops are ignored (as they are assumed to all be
-/// equal), however the enabled/disabled bit on such channels as well as the
-/// htlc_minimum_msat/htlc_maximum_msat *are* checked as they may change based on the receiving node.
-pub fn get_route<L: Deref, S: routing::Score>(
+pub(crate) fn get_route<L: Deref, S: routing::Score>(
our_node_pubkey: &PublicKey, payee: &Payee, network: &NetworkGraph,
- first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, final_cltv: u32, logger: L,
- scorer: &S
+ first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, final_cltv_expiry_delta: u32,
+ logger: L, scorer: &S
) -> Result<Route, LightningError>
where L::Target: Logger {
let payee_node_id = NodeId::from_pubkey(&payee.pubkey);
}
ordered_hops.last_mut().unwrap().0.fee_msat = value_contribution_msat;
ordered_hops.last_mut().unwrap().0.hop_use_fee_msat = 0;
- ordered_hops.last_mut().unwrap().0.cltv_expiry_delta = final_cltv;
+ ordered_hops.last_mut().unwrap().0.cltv_expiry_delta = final_cltv_expiry_delta;
log_trace!(logger, "Found a path back to us from the target with {} hops contributing up to {} msat: {:?}",
ordered_hops.len(), value_contribution_msat, ordered_hops);
}
}
- let route = Route { paths: selected_paths.into_iter().map(|path| path.into_iter().collect()).collect::<Result<Vec<_>, _>>()? };
+ let route = Route {
+ paths: selected_paths.into_iter().map(|path| path.into_iter().collect()).collect::<Result<Vec<_>, _>>()?,
+ payee: Some(payee.clone()),
+ };
log_info!(logger, "Got route to {}: {}", payee.pubkey, log_route!(route));
Ok(route)
}
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
let payee = Payee::new(nodes[2]);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// Simple route to 2 via 1
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
let payee = Payee::new(nodes[2]);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// Simple route to 2 via 1
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
let payee = Payee::new(nodes[2]);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// Simple route to 2 via 1
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
let payee = Payee::new(nodes[2]).with_features(InvoiceFeatures::known());
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// A route to node#2 via two paths.
// One path allows transferring 35-40 sats, another one also allows 35-40 sats.
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
let payee = Payee::new(nodes[2]);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// // Disable channels 4 and 12 by flags=2
update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
let payee = Payee::new(nodes[2]);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// Disable nodes 1, 2, and 8 by requiring unknown feature bits
let unknown_features = NodeFeatures::known().set_unknown_feature_required();
fn our_chans_test() {
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// Route to 1 via 2 and 3 because our channel to 1 is disabled
let payee = Payee::new(nodes[0]);
fn partial_route_hint_test() {
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// Simple test across 2, 3, 5, and 4 via a last_hop channel
// Tests the behaviour when the RouteHint contains a suboptimal hop.
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
let payee = Payee::new(nodes[6]).with_route_hints(empty_last_hop(&nodes));
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// Test handling of an empty RouteHint passed in Invoice.
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
let payee = Payee::new(nodes[6]).with_route_hints(multi_hint_last_hops(&nodes));
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// Test through channels 2, 3, 5, 8.
// Test shows that multiple hop hints are considered.
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
let payee = Payee::new(nodes[6]).with_route_hints(last_hops_with_public_channel(&nodes));
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// This test shows that public routes can be present in the invoice
// which would be handled in the same manner.
fn our_chans_last_hop_connect_test() {
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// Simple test with outbound channel to 4 to test that last_hops and first_hops connect
let our_chans = vec![get_channel_details(Some(42), nodes[3].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
}]);
let payee = Payee::new(target_node_id).with_route_hints(vec![last_hops]);
let our_chans = vec![get_channel_details(Some(42), middle_node_id, InitFeatures::from_le_bytes(vec![0b11]), outbound_capacity_msat)];
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
get_route(&source_node_id, &payee, &NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash()), Some(&our_chans.iter().collect::<Vec<_>>()), route_val, 42, &test_utils::TestLogger::new(), &scorer)
}
let (secp_ctx, mut net_graph_msg_handler, chain_monitor, logger) = build_graph();
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let payee = Payee::new(nodes[2]).with_features(InvoiceFeatures::known());
// We will use a simple single-path route from
// one of the latter hops is limited.
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let payee = Payee::new(nodes[3]).with_features(InvoiceFeatures::known());
// Path via {node7, node2, node4} is channels {12, 13, 6, 11}.
fn ignore_fee_first_hop_test() {
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let payee = Payee::new(nodes[2]);
// Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50).
fn simple_mpp_route_test() {
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let payee = Payee::new(nodes[2]).with_features(InvoiceFeatures::known());
// We need a route consisting of 3 paths:
fn long_mpp_route_test() {
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let payee = Payee::new(nodes[3]).with_features(InvoiceFeatures::known());
// We need a route consisting of 3 paths:
fn mpp_cheaper_route_test() {
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let payee = Payee::new(nodes[3]).with_features(InvoiceFeatures::known());
// This test checks that if we have two cheaper paths and one more expensive path,
// if the fee is not properly accounted for, the behavior is different.
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let payee = Payee::new(nodes[3]).with_features(InvoiceFeatures::known());
// We need a route consisting of 2 paths:
// path finding we realize that we found more capacity than we need.
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let payee = Payee::new(nodes[2]).with_features(InvoiceFeatures::known());
// We need a route consisting of 3 paths:
let network_graph = NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash());
let net_graph_msg_handler = NetGraphMsgHandler::new(network_graph, None, Arc::clone(&logger));
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let payee = Payee::new(nodes[6]);
add_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, &privkeys[1], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6);
// we calculated fees on a higher value, resulting in us ignoring such paths.
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (our_privkey, our_id, _, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let payee = Payee::new(nodes[2]);
// We modify the graph to set the htlc_maximum of channel 2 to below the value we wish to
// resulting in us thinking there is no possible path, even if other paths exist.
let (secp_ctx, net_graph_msg_handler, _, logger) = build_graph();
let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let payee = Payee::new(nodes[2]).with_features(InvoiceFeatures::known());
// We modify the graph to set the htlc_minimum of channel 2 and 4 as needed - channel 2
let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
let logger = Arc::new(test_utils::TestLogger::new());
let network_graph = NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash());
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let payee = Payee::new(nodes[0]).with_features(InvoiceFeatures::known());
{
let payee = Payee::new(nodes[6]).with_route_hints(last_hops(&nodes));
// Without penalizing each hop 100 msats, a longer path with lower fees is chosen.
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let route = get_route(
&our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42,
Arc::clone(&logger), &scorer
// Applying a 100 msat penalty to each hop results in taking channels 7 and 10 to nodes[6]
// from nodes[2] rather than channel 6, 11, and 8, even though the longer path is cheaper.
- let scorer = Scorer::new(100);
+ let scorer = Scorer::with_fixed_penalty(100);
let route = get_route(
&our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42,
Arc::clone(&logger), &scorer
fn channel_penalty_msat(&self, short_channel_id: u64, _source: &NodeId, _target: &NodeId) -> u64 {
if short_channel_id == self.short_channel_id { u64::max_value() } else { 0 }
}
+
+ fn payment_path_failed(&mut self, _path: &Vec<RouteHop>, _short_channel_id: u64) {}
}
struct BadNodeScorer {
fn channel_penalty_msat(&self, _short_channel_id: u64, _source: &NodeId, target: &NodeId) -> u64 {
if *target == self.node_id { u64::max_value() } else { 0 }
}
+
+ fn payment_path_failed(&mut self, _path: &Vec<RouteHop>, _short_channel_id: u64) {}
}
#[test]
let payee = Payee::new(nodes[6]).with_route_hints(last_hops(&nodes));
// A path to nodes[6] exists when no penalties are applied to any channel.
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
let route = get_route(
&our_id, &payee, &net_graph_msg_handler.network_graph, None, 100, 42,
Arc::clone(&logger), &scorer
short_channel_id: 0, fee_msat: 225, cltv_expiry_delta: 0
},
]],
+ payee: None,
};
assert_eq!(route.get_total_fees(), 250);
short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0
},
]],
+ payee: None,
};
assert_eq!(route.get_total_fees(), 200);
// In an earlier version of `Route::get_total_fees` and `Route::get_total_amount`, they
// would both panic if the route was completely empty. We test to ensure they return 0
// here, even though its somewhat nonsensical as a route.
- let route = Route { paths: Vec::new() };
+ let route = Route { paths: Vec::new(), payee: None };
assert_eq!(route.get_total_fees(), 0);
assert_eq!(route.get_total_amount(), 0);
},
};
let graph = NetworkGraph::read(&mut d).unwrap();
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
let mut seed = random_init_seed() as usize;
},
};
let graph = NetworkGraph::read(&mut d).unwrap();
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
let mut seed = random_init_seed() as usize;
let mut d = test_utils::get_route_file().unwrap();
let graph = NetworkGraph::read(&mut d).unwrap();
let nodes = graph.read_only().nodes().clone();
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
let mut path_endpoints = Vec::new();
let mut d = test_utils::get_route_file().unwrap();
let graph = NetworkGraph::read(&mut d).unwrap();
let nodes = graph.read_only().nodes().clone();
- let scorer = Scorer::new(0);
+ let scorer = Scorer::with_fixed_penalty(0);
// First, get 100 (source, destination) pairs for which route-getting actually succeeds...
let mut path_endpoints = Vec::new();