///
/// [`BlindedPath`]: crate::blinded_path::BlindedPath
pub cltv_expiry_delta: u32,
+ /// Indicates whether this hop is possibly announced in the public network graph.
+ ///
+ /// Will be `true` if there is a possibility that the channel is publicly known, i.e., if we
+ /// either know for sure it's announced in the public graph, or if any public channels exist
+ /// for which the given `short_channel_id` could be an alias for. Will be `false` if we believe
+ /// the channel to be unannounced.
+ ///
+ /// Will be `true` for objects serialized with LDK version 0.0.116 and before.
+ pub maybe_announced_channel: bool,
}
impl_writeable_tlv_based!(RouteHop, {
(0, pubkey, required),
+ (1, maybe_announced_channel, (default_value, true)),
(2, node_features, required),
(4, short_channel_id, required),
(6, channel_features, required),
// Decrease the available liquidity of a hop in the middle of the path.
let victim_candidate = &payment_path.hops[(payment_path.hops.len()) / 2].0.candidate;
let exhausted = u64::max_value();
- log_trace!(logger, "Disabling route candidate {} for future path building iterations to
- avoid duplicates.", LoggedCandidateHop(victim_candidate));
+ log_trace!(logger,
+ "Disabling route candidate {} for future path building iterations to avoid duplicates.",
+ LoggedCandidateHop(victim_candidate));
*used_liquidities.entry(victim_candidate.id(false)).or_default() = exhausted;
*used_liquidities.entry(victim_candidate.id(true)).or_default() = exhausted;
}
let mut paths = Vec::new();
for payment_path in selected_route {
let mut hops = Vec::with_capacity(payment_path.hops.len());
+ let mut prev_hop_node_id = our_node_id;
for (hop, node_features) in payment_path.hops.iter()
.filter(|(h, _)| h.candidate.short_channel_id().is_some())
{
+ let maybe_announced_channel = if let CandidateRouteHop::PublicHop { .. } = hop.candidate {
+ // If we sourced the hop from the graph we're sure the target node is announced.
+ true
+ } else if let CandidateRouteHop::FirstHop { details } = hop.candidate {
+ // If this is a first hop we also know if it's announced.
+ details.is_public
+ } else {
+ // If we sourced it any other way, we double-check the network graph to see if
+ // there are announced channels between the endpoints. If so, the hop might be
+ // referring to any of the announced channels, as its `short_channel_id` might be
+ // an alias, in which case we don't take any chances here.
+ network_graph.node(&hop.node_id).map_or(false, |hop_node|
+ hop_node.channels.iter().any(|scid| network_graph.channel(*scid)
+ .map_or(false, |c| c.as_directed_from(&prev_hop_node_id).is_some()))
+ )
+ };
+
hops.push(RouteHop {
pubkey: PublicKey::from_slice(hop.node_id.as_slice()).map_err(|_| LightningError{err: format!("Public key {:?} is invalid", &hop.node_id), action: ErrorAction::IgnoreAndLog(Level::Trace)})?,
node_features: node_features.clone(),
channel_features: hop.candidate.features(),
fee_msat: hop.fee_msat,
cltv_expiry_delta: hop.candidate.cltv_expiry_delta(),
+ maybe_announced_channel,
});
+
+ prev_hop_node_id = hop.node_id;
}
let mut final_cltv_delta = final_cltv_expiry_delta;
let blinded_tail = payment_path.hops.last().and_then(|(h, _)| {
RouteHop {
pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
- short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0
+ short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0, maybe_announced_channel: true,
},
RouteHop {
pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
- short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0
+ short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0, maybe_announced_channel: true,
},
RouteHop {
pubkey: PublicKey::from_slice(&hex::decode("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()[..]).unwrap(),
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
- short_channel_id: 0, fee_msat: 225, cltv_expiry_delta: 0
+ short_channel_id: 0, fee_msat: 225, cltv_expiry_delta: 0, maybe_announced_channel: true,
},
], blinded_tail: None }],
route_params: None,
RouteHop {
pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
- short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0
+ short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0, maybe_announced_channel: true,
},
RouteHop {
pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
- short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0
+ short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0, maybe_announced_channel: true,
},
], blinded_tail: None }, Path { hops: vec![
RouteHop {
pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
- short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0
+ short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0, maybe_announced_channel: true,
},
RouteHop {
pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
- short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0
+ short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0, maybe_announced_channel: true,
},
], blinded_tail: None }],
route_params: None,
channel_features: ChannelFeatures::empty(),
fee_msat: 100,
cltv_expiry_delta: 0,
+ maybe_announced_channel: true,
}],
blinded_tail: Some(BlindedTail {
hops: blinded_path_1.blinded_hops,
channel_features: ChannelFeatures::empty(),
fee_msat: 100,
cltv_expiry_delta: 0,
+ maybe_announced_channel: true,
}], blinded_tail: None }],
route_params: None,
};
channel_features: ChannelFeatures::empty(),
fee_msat: 100,
cltv_expiry_delta: 0,
+ maybe_announced_channel: false,
},
RouteHop {
pubkey: blinded_path.introduction_node_id,
channel_features: ChannelFeatures::empty(),
fee_msat: 1,
cltv_expiry_delta: 0,
+ maybe_announced_channel: false,
}],
blinded_tail: Some(BlindedTail {
hops: blinded_path.blinded_hops,
channel_features: ChannelFeatures::empty(),
fee_msat: 100,
cltv_expiry_delta: 0,
+ maybe_announced_channel: false,
},
RouteHop {
pubkey: blinded_path.introduction_node_id,
channel_features: ChannelFeatures::empty(),
fee_msat: 1,
cltv_expiry_delta: 0,
+ maybe_announced_channel: false,
}
],
blinded_tail: Some(BlindedTail {
"generate_large_mpp_routes_with_probabilistic_scorer");
}
+ pub fn generate_routes_with_nonlinear_probabilistic_scorer(bench: &mut Criterion) {
+ let logger = TestLogger::new();
+ let network_graph = bench_utils::read_network_graph(&logger).unwrap();
+ let mut params = ProbabilisticScoringFeeParameters::default();
+ params.linear_success_probability = false;
+ let scorer = ProbabilisticScorer::new(
+ ProbabilisticScoringDecayParameters::default(), &network_graph, &logger);
+ generate_routes(bench, &network_graph, scorer, ¶ms,
+ channelmanager::provided_invoice_features(&UserConfig::default()), 0,
+ "generate_routes_with_nonlinear_probabilistic_scorer");
+ }
+
+ pub fn generate_mpp_routes_with_nonlinear_probabilistic_scorer(bench: &mut Criterion) {
+ let logger = TestLogger::new();
+ let network_graph = bench_utils::read_network_graph(&logger).unwrap();
+ let mut params = ProbabilisticScoringFeeParameters::default();
+ params.linear_success_probability = false;
+ let scorer = ProbabilisticScorer::new(
+ ProbabilisticScoringDecayParameters::default(), &network_graph, &logger);
+ generate_routes(bench, &network_graph, scorer, ¶ms,
+ channelmanager::provided_invoice_features(&UserConfig::default()), 0,
+ "generate_mpp_routes_with_nonlinear_probabilistic_scorer");
+ }
+
+ pub fn generate_large_mpp_routes_with_nonlinear_probabilistic_scorer(bench: &mut Criterion) {
+ let logger = TestLogger::new();
+ let network_graph = bench_utils::read_network_graph(&logger).unwrap();
+ let mut params = ProbabilisticScoringFeeParameters::default();
+ params.linear_success_probability = false;
+ let scorer = ProbabilisticScorer::new(
+ ProbabilisticScoringDecayParameters::default(), &network_graph, &logger);
+ generate_routes(bench, &network_graph, scorer, ¶ms,
+ channelmanager::provided_invoice_features(&UserConfig::default()), 100_000_000,
+ "generate_large_mpp_routes_with_nonlinear_probabilistic_scorer");
+ }
+
fn generate_routes<S: ScoreLookUp + ScoreUpdate>(
bench: &mut Criterion, graph: &NetworkGraph<&TestLogger>, mut scorer: S,
score_params: &S::ScoreParams, features: Bolt11InvoiceFeatures, starting_amount: u64,