1use bitcoin::secp256k1::{self, PublicKey, Secp256k1};
13use lightning_invoice::Bolt11Invoice;
14
15use crate::blinded_path::payment::{
16 BlindedPaymentPath, ForwardTlvs, PaymentConstraints, PaymentForwardNode, PaymentRelay,
17 ReceiveTlvs,
18};
19use crate::blinded_path::{BlindedHop, Direction, IntroductionNode};
20use crate::crypto::chacha20::ChaCha20;
21use crate::ln::channel_state::ChannelDetails;
22use crate::ln::channelmanager::{PaymentId, RecipientOnionFields, MIN_FINAL_CLTV_EXPIRY_DELTA};
23use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
24use crate::ln::onion_utils;
25use crate::offers::invoice::Bolt12Invoice;
26use crate::offers::static_invoice::StaticInvoice;
27use crate::routing::gossip::{
28 DirectedChannelInfo, EffectiveCapacity, NetworkGraph, NodeId, ReadOnlyNetworkGraph,
29};
30use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp};
31use crate::sign::EntropySource;
32use crate::sync::Mutex;
33use crate::types::features::{
34 BlindedHopFeatures, Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures,
35};
36use crate::types::payment::{PaymentHash, PaymentPreimage};
37use crate::util::logger::Logger;
38use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
39
40use crate::io;
41use crate::prelude::*;
42use alloc::collections::BinaryHeap;
43use core::ops::Deref;
44use core::{cmp, fmt};
45
46use lightning_types::routing::RoutingFees;
47
48pub use lightning_types::routing::{RouteHint, RouteHintHop};
49
50pub struct DefaultRouter<
59 G: Deref<Target = NetworkGraph<L>>,
60 L: Deref,
61 ES: Deref,
62 S: Deref,
63 SP: Sized,
64 Sc: ScoreLookUp<ScoreParams = SP>,
65> where
66 L::Target: Logger,
67 S::Target: for<'a> LockableScore<'a, ScoreLookUp = Sc>,
68 ES::Target: EntropySource,
69{
70 network_graph: G,
71 logger: L,
72 entropy_source: ES,
73 scorer: S,
74 score_params: SP,
75}
76
77impl<
78 G: Deref<Target = NetworkGraph<L>>,
79 L: Deref,
80 ES: Deref,
81 S: Deref,
82 SP: Sized,
83 Sc: ScoreLookUp<ScoreParams = SP>,
84 > DefaultRouter<G, L, ES, S, SP, Sc>
85where
86 L::Target: Logger,
87 S::Target: for<'a> LockableScore<'a, ScoreLookUp = Sc>,
88 ES::Target: EntropySource,
89{
90 pub fn new(
92 network_graph: G, logger: L, entropy_source: ES, scorer: S, score_params: SP,
93 ) -> Self {
94 Self { network_graph, logger, entropy_source, scorer, score_params }
95 }
96}
97
98impl<
99 G: Deref<Target = NetworkGraph<L>>,
100 L: Deref,
101 ES: Deref,
102 S: Deref,
103 SP: Sized,
104 Sc: ScoreLookUp<ScoreParams = SP>,
105 > Router for DefaultRouter<G, L, ES, S, SP, Sc>
106where
107 L::Target: Logger,
108 S::Target: for<'a> LockableScore<'a, ScoreLookUp = Sc>,
109 ES::Target: EntropySource,
110{
111 #[rustfmt::skip]
112 fn find_route(
113 &self,
114 payer: &PublicKey,
115 params: &RouteParameters,
116 first_hops: Option<&[&ChannelDetails]>,
117 inflight_htlcs: InFlightHtlcs
118 ) -> Result<Route, &'static str> {
119 let random_seed_bytes = self.entropy_source.get_secure_random_bytes();
120 find_route(
121 payer, params, &self.network_graph, first_hops, &*self.logger,
122 &ScorerAccountingForInFlightHtlcs::new(self.scorer.read_lock(), &inflight_htlcs),
123 &self.score_params,
124 &random_seed_bytes
125 )
126 }
127
128 #[rustfmt::skip]
129 fn create_blinded_payment_paths<
130 T: secp256k1::Signing + secp256k1::Verification
131 > (
132 &self, recipient: PublicKey, first_hops: Vec<ChannelDetails>, tlvs: ReceiveTlvs,
133 amount_msats: Option<u64>, secp_ctx: &Secp256k1<T>
134 ) -> Result<Vec<BlindedPaymentPath>, ()> {
135 const MAX_PAYMENT_PATHS: usize = 3;
137
138 const MIN_PEER_CHANNELS: usize = 3;
141
142 let has_one_peer = first_hops
143 .first()
144 .map(|details| details.counterparty.node_id)
145 .map(|node_id| first_hops
146 .iter()
147 .skip(1)
148 .all(|details| details.counterparty.node_id == node_id)
149 )
150 .unwrap_or(false);
151
152 let network_graph = self.network_graph.deref().read_only();
153 let is_recipient_announced =
154 network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient));
155
156 let paths = first_hops.into_iter()
157 .filter(|details| details.counterparty.features.supports_route_blinding())
158 .filter(|details| amount_msats.unwrap_or(0) <= details.inbound_capacity_msat)
159 .filter(|details| amount_msats.unwrap_or(u64::MAX) >= details.inbound_htlc_minimum_msat.unwrap_or(0))
160 .filter(|details| amount_msats.unwrap_or(0) <= details.inbound_htlc_maximum_msat.unwrap_or(u64::MAX))
161 .filter(|details| network_graph
163 .node(&NodeId::from_pubkey(&details.counterparty.node_id))
164 .map(|node| !is_recipient_announced || node.channels.len() >= MIN_PEER_CHANNELS)
165 .unwrap_or(!is_recipient_announced && has_one_peer)
167 )
168 .filter_map(|details| {
169 let short_channel_id = match details.get_inbound_payment_scid() {
170 Some(short_channel_id) => short_channel_id,
171 None => return None,
172 };
173 let payment_relay: PaymentRelay = match details.counterparty.forwarding_info {
174 Some(forwarding_info) => match forwarding_info.try_into() {
175 Ok(payment_relay) => payment_relay,
176 Err(()) => return None,
177 },
178 None => return None,
179 };
180
181 let cltv_expiry_delta = payment_relay.cltv_expiry_delta as u32;
182 let payment_constraints = PaymentConstraints {
183 max_cltv_expiry: tlvs.tlvs().payment_constraints.max_cltv_expiry + cltv_expiry_delta,
184 htlc_minimum_msat: details.inbound_htlc_minimum_msat.unwrap_or(0),
185 };
186 Some(PaymentForwardNode {
187 tlvs: ForwardTlvs {
188 short_channel_id,
189 payment_relay,
190 payment_constraints,
191 next_blinding_override: None,
192 features: BlindedHopFeatures::empty(),
193 },
194 node_id: details.counterparty.node_id,
195 htlc_maximum_msat: details.inbound_htlc_maximum_msat.unwrap_or(u64::MAX),
196 })
197 })
198 .map(|forward_node| {
199 BlindedPaymentPath::new(
200 &[forward_node], recipient, tlvs.clone(), u64::MAX, MIN_FINAL_CLTV_EXPIRY_DELTA,
201 &*self.entropy_source, secp_ctx
202 )
203 })
204 .take(MAX_PAYMENT_PATHS)
205 .collect::<Result<Vec<_>, _>>();
206
207 match paths {
208 Ok(paths) if !paths.is_empty() => Ok(paths),
209 _ => {
210 if network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient)) {
211 BlindedPaymentPath::new(
212 &[], recipient, tlvs, u64::MAX, MIN_FINAL_CLTV_EXPIRY_DELTA, &*self.entropy_source,
213 secp_ctx
214 ).map(|path| vec![path])
215 } else {
216 Err(())
217 }
218 },
219 }
220 }
221}
222
223pub(crate) struct FixedRouter {
227 route: Mutex<Option<Route>>,
229}
230
231impl FixedRouter {
232 pub(crate) fn new(route: Route) -> Self {
233 Self { route: Mutex::new(Some(route)) }
234 }
235}
236
237impl Router for FixedRouter {
238 fn find_route(
239 &self, _payer: &PublicKey, _route_params: &RouteParameters,
240 _first_hops: Option<&[&ChannelDetails]>, _inflight_htlcs: InFlightHtlcs,
241 ) -> Result<Route, &'static str> {
242 self.route.lock().unwrap().take().ok_or("Can't use this router to return multiple routes")
243 }
244
245 fn create_blinded_payment_paths<T: secp256k1::Signing + secp256k1::Verification>(
246 &self, _recipient: PublicKey, _first_hops: Vec<ChannelDetails>, _tlvs: ReceiveTlvs,
247 _amount_msats: Option<u64>, _secp_ctx: &Secp256k1<T>,
248 ) -> Result<Vec<BlindedPaymentPath>, ()> {
249 debug_assert!(false);
251 Err(())
252 }
253}
254
255pub trait Router {
257 #[rustfmt::skip]
262 fn find_route(
263 &self, payer: &PublicKey, route_params: &RouteParameters,
264 first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: InFlightHtlcs
265 ) -> Result<Route, &'static str>;
266
267 fn find_route_with_id(
275 &self, payer: &PublicKey, route_params: &RouteParameters,
276 first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: InFlightHtlcs,
277 _payment_hash: PaymentHash, _payment_id: PaymentId,
278 ) -> Result<Route, &'static str> {
279 self.find_route(payer, route_params, first_hops, inflight_htlcs)
280 }
281
282 fn create_blinded_payment_paths<T: secp256k1::Signing + secp256k1::Verification>(
286 &self, recipient: PublicKey, first_hops: Vec<ChannelDetails>, tlvs: ReceiveTlvs,
287 amount_msats: Option<u64>, secp_ctx: &Secp256k1<T>,
288 ) -> Result<Vec<BlindedPaymentPath>, ()>;
289}
290
291pub struct ScorerAccountingForInFlightHtlcs<'a, S: Deref>
298where
299 S::Target: ScoreLookUp,
300{
301 scorer: S,
302 inflight_htlcs: &'a InFlightHtlcs,
304}
305impl<'a, S: Deref> ScorerAccountingForInFlightHtlcs<'a, S>
306where
307 S::Target: ScoreLookUp,
308{
309 #[rustfmt::skip]
311 pub fn new(scorer: S, inflight_htlcs: &'a InFlightHtlcs) -> Self {
312 ScorerAccountingForInFlightHtlcs {
313 scorer,
314 inflight_htlcs
315 }
316 }
317}
318
319impl<'a, S: Deref> ScoreLookUp for ScorerAccountingForInFlightHtlcs<'a, S>
320where
321 S::Target: ScoreLookUp,
322{
323 type ScoreParams = <S::Target as ScoreLookUp>::ScoreParams;
324 #[rustfmt::skip]
325 fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, usage: ChannelUsage, score_params: &Self::ScoreParams) -> u64 {
326 let target = match candidate.target() {
327 Some(target) => target,
328 None => return self.scorer.channel_penalty_msat(candidate, usage, score_params),
329 };
330 let short_channel_id = match candidate.short_channel_id() {
331 Some(short_channel_id) => short_channel_id,
332 None => return self.scorer.channel_penalty_msat(candidate, usage, score_params),
333 };
334 let source = candidate.source();
335 if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity_msat(
336 &source, &target, short_channel_id
337 ) {
338 let usage = ChannelUsage {
339 inflight_htlc_msat: usage.inflight_htlc_msat.saturating_add(used_liquidity),
340 ..usage
341 };
342
343 self.scorer.channel_penalty_msat(candidate, usage, score_params)
344 } else {
345 self.scorer.channel_penalty_msat(candidate, usage, score_params)
346 }
347 }
348}
349
350#[derive(Clone)]
353pub struct InFlightHtlcs(
354 HashMap<(u64, bool), u64>,
359);
360
361impl InFlightHtlcs {
362 #[rustfmt::skip]
364 pub fn new() -> Self { InFlightHtlcs(new_hash_map()) }
365
366 #[rustfmt::skip]
368 pub fn process_path(&mut self, path: &Path, payer_node_id: PublicKey) {
369 if path.hops.is_empty() { return };
370
371 let mut cumulative_msat = 0;
372 if let Some(tail) = &path.blinded_tail {
373 cumulative_msat += tail.final_value_msat;
374 }
375
376 let reversed_hops_with_payer = path.hops.iter().rev().skip(1)
382 .map(|hop| hop.pubkey)
383 .chain(core::iter::once(payer_node_id));
384
385 for (next_hop, prev_hop) in path.hops.iter().rev().zip(reversed_hops_with_payer) {
389 cumulative_msat += next_hop.fee_msat;
390 self.0
391 .entry((next_hop.short_channel_id, NodeId::from_pubkey(&prev_hop) < NodeId::from_pubkey(&next_hop.pubkey)))
392 .and_modify(|used_liquidity_msat| *used_liquidity_msat += cumulative_msat)
393 .or_insert(cumulative_msat);
394 }
395 }
396
397 pub fn add_inflight_htlc(
400 &mut self, source: &NodeId, target: &NodeId, channel_scid: u64, used_msat: u64,
401 ) {
402 self.0
403 .entry((channel_scid, source < target))
404 .and_modify(|used_liquidity_msat| *used_liquidity_msat += used_msat)
405 .or_insert(used_msat);
406 }
407
408 pub fn used_liquidity_msat(
411 &self, source: &NodeId, target: &NodeId, channel_scid: u64,
412 ) -> Option<u64> {
413 self.0.get(&(channel_scid, source < target)).map(|v| *v)
414 }
415}
416
417impl Writeable for InFlightHtlcs {
418 #[rustfmt::skip]
419 fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> { self.0.write(writer) }
420}
421
422impl Readable for InFlightHtlcs {
423 fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
424 let infight_map: HashMap<(u64, bool), u64> = Readable::read(reader)?;
425 Ok(Self(infight_map))
426 }
427}
428
429#[derive(Clone, Debug, Hash, PartialEq, Eq)]
432pub struct RouteHop {
433 pub pubkey: PublicKey,
435 pub node_features: NodeFeatures,
438 pub short_channel_id: u64,
440 pub channel_features: ChannelFeatures,
443 pub fee_msat: u64,
449 pub cltv_expiry_delta: u32,
455 pub maybe_announced_channel: bool,
464}
465
466impl_writeable_tlv_based!(RouteHop, {
467 (0, pubkey, required),
468 (1, maybe_announced_channel, (default_value, true)),
469 (2, node_features, required),
470 (4, short_channel_id, required),
471 (6, channel_features, required),
472 (8, fee_msat, required),
473 (10, cltv_expiry_delta, required),
474});
475
476#[derive(Clone, Debug, Hash, PartialEq, Eq)]
478pub struct TrampolineHop {
479 pub pubkey: PublicKey,
481 pub node_features: NodeFeatures,
483 pub fee_msat: u64,
488 pub cltv_expiry_delta: u32,
492}
493
494impl_writeable_tlv_based!(TrampolineHop, {
495 (0, pubkey, required),
496 (2, node_features, required),
497 (4, fee_msat, required),
498 (6, cltv_expiry_delta, required),
499});
500
501#[derive(Clone, Debug, Hash, PartialEq, Eq)]
506pub struct BlindedTail {
507 pub trampoline_hops: Vec<TrampolineHop>,
513 pub hops: Vec<BlindedHop>,
515 pub blinding_point: PublicKey,
517 pub excess_final_cltv_expiry_delta: u32,
520 pub final_value_msat: u64,
522}
523
524impl_writeable_tlv_based!(BlindedTail, {
525 (0, hops, required_vec),
526 (2, blinding_point, required),
527 (4, excess_final_cltv_expiry_delta, required),
528 (6, final_value_msat, required),
529 (8, trampoline_hops, optional_vec),
530});
531
532#[derive(Clone, Debug, Hash, PartialEq, Eq)]
535pub struct Path {
536 pub hops: Vec<RouteHop>,
538 pub blinded_tail: Option<BlindedTail>,
540}
541
542impl Path {
543 #[rustfmt::skip]
545 pub fn fee_msat(&self) -> u64 {
546 match &self.blinded_tail {
547 Some(_) => self.hops.iter().map(|hop| hop.fee_msat).sum::<u64>(),
548 None => {
549 self.hops.split_last().map_or(0,
551 |(_, path_prefix)| path_prefix.iter().map(|hop| hop.fee_msat).sum())
552 }
553 }
554 }
555
556 #[rustfmt::skip]
558 pub fn final_value_msat(&self) -> u64 {
559 match &self.blinded_tail {
560 Some(blinded_tail) => blinded_tail.final_value_msat,
561 None => self.hops.last().map_or(0, |hop| hop.fee_msat)
562 }
563 }
564
565 #[rustfmt::skip]
567 pub fn final_cltv_expiry_delta(&self) -> Option<u32> {
568 match &self.blinded_tail {
569 Some(_) => None,
570 None => self.hops.last().map(|hop| hop.cltv_expiry_delta)
571 }
572 }
573
574 pub fn has_trampoline_hops(&self) -> bool {
576 self.blinded_tail.as_ref().map_or(false, |bt| !bt.trampoline_hops.is_empty())
577 }
578}
579
580#[derive(Clone, Debug, Hash, PartialEq, Eq)]
583pub struct Route {
584 pub paths: Vec<Path>,
588 pub route_params: Option<RouteParameters>,
594}
595
596impl Route {
597 #[rustfmt::skip]
605 pub fn get_total_fees(&self) -> u64 {
606 let overpaid_value_msat = self.route_params.as_ref()
607 .map_or(0, |p| self.get_total_amount().saturating_sub(p.final_value_msat));
608 overpaid_value_msat + self.paths.iter().map(|path| path.fee_msat()).sum::<u64>()
609 }
610
611 pub fn get_total_amount(&self) -> u64 {
618 self.paths.iter().map(|path| path.final_value_msat()).sum()
619 }
620}
621
622impl fmt::Display for Route {
623 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
624 log_route!(self).fmt(f)
625 }
626}
627
628const SERIALIZATION_VERSION: u8 = 1;
629const MIN_SERIALIZATION_VERSION: u8 = 1;
630
631impl Writeable for Route {
632 #[rustfmt::skip]
633 fn write<W: crate::util::ser::Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
634 write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
635 (self.paths.len() as u64).write(writer)?;
636 let mut blinded_tails = Vec::new();
637 for (idx, path) in self.paths.iter().enumerate() {
638 (path.hops.len() as u8).write(writer)?;
639 for hop in path.hops.iter() {
640 hop.write(writer)?;
641 }
642 if let Some(blinded_tail) = &path.blinded_tail {
643 if blinded_tails.is_empty() {
644 blinded_tails = Vec::with_capacity(path.hops.len());
645 for _ in 0..idx {
646 blinded_tails.push(None);
647 }
648 }
649 blinded_tails.push(Some(blinded_tail));
650 } else if !blinded_tails.is_empty() { blinded_tails.push(None); }
651 }
652 write_tlv_fields!(writer, {
653 (1, self.route_params.as_ref().map(|p| &p.payment_params), option),
656 (2, blinded_tails, optional_vec),
657 (3, self.route_params.as_ref().map(|p| p.final_value_msat), option),
658 (5, self.route_params.as_ref().and_then(|p| p.max_total_routing_fee_msat), option),
659 });
660 Ok(())
661 }
662}
663
664impl Readable for Route {
665 #[rustfmt::skip]
666 fn read<R: io::Read>(reader: &mut R) -> Result<Route, DecodeError> {
667 let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
668 let path_count: u64 = Readable::read(reader)?;
669 if path_count == 0 { return Err(DecodeError::InvalidValue); }
670 let mut paths = Vec::with_capacity(cmp::min(path_count, 128) as usize);
671 let mut min_final_cltv_expiry_delta = u32::max_value();
672 for _ in 0..path_count {
673 let hop_count: u8 = Readable::read(reader)?;
674 let mut hops: Vec<RouteHop> = Vec::with_capacity(hop_count as usize);
675 for _ in 0..hop_count {
676 hops.push(Readable::read(reader)?);
677 }
678 if hops.is_empty() { return Err(DecodeError::InvalidValue); }
679 min_final_cltv_expiry_delta =
680 cmp::min(min_final_cltv_expiry_delta, hops.last().unwrap().cltv_expiry_delta);
681 paths.push(Path { hops, blinded_tail: None });
682 }
683 _init_and_read_len_prefixed_tlv_fields!(reader, {
684 (1, payment_params, (option: ReadableArgs, min_final_cltv_expiry_delta)),
685 (2, blinded_tails, optional_vec),
686 (3, final_value_msat, option),
687 (5, max_total_routing_fee_msat, option)
688 });
689 let blinded_tails = blinded_tails.unwrap_or(Vec::new());
690 if blinded_tails.len() != 0 {
691 if blinded_tails.len() != paths.len() { return Err(DecodeError::InvalidValue) }
692 for (path, blinded_tail_opt) in paths.iter_mut().zip(blinded_tails.into_iter()) {
693 path.blinded_tail = blinded_tail_opt;
694 }
695 }
696
697 let route_params = match (payment_params, final_value_msat) {
699 (Some(payment_params), Some(final_value_msat)) => {
700 Some(RouteParameters { payment_params, final_value_msat, max_total_routing_fee_msat })
701 }
702 _ => None,
703 };
704
705 Ok(Route { paths, route_params })
706 }
707}
708
709#[derive(Clone, Debug, Hash, PartialEq, Eq)]
713pub struct RouteParameters {
714 pub payment_params: PaymentParameters,
716
717 pub final_value_msat: u64,
719
720 pub max_total_routing_fee_msat: Option<u64>,
727}
728
729impl RouteParameters {
730 #[rustfmt::skip]
734 pub fn from_payment_params_and_value(payment_params: PaymentParameters, final_value_msat: u64) -> Self {
735 Self { payment_params, final_value_msat, max_total_routing_fee_msat: Some(final_value_msat / 100 + 50_000) }
736 }
737
738 #[rustfmt::skip]
741 pub fn set_max_path_length(
742 &mut self, recipient_onion: &RecipientOnionFields, is_keysend: bool, best_block_height: u32
743 ) -> Result<(), ()> {
744 let keysend_preimage_opt = is_keysend.then(|| PaymentPreimage([42; 32]));
745 onion_utils::set_max_path_length(
747 self, recipient_onion, keysend_preimage_opt, None, best_block_height
748 )
749 }
750}
751
752impl Writeable for RouteParameters {
753 fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
754 write_tlv_fields!(writer, {
755 (0, self.payment_params, required),
756 (1, self.max_total_routing_fee_msat, option),
757 (2, self.final_value_msat, required),
758 (4, self.payment_params.payee.final_cltv_expiry_delta(), option),
761 });
762 Ok(())
763 }
764}
765
766impl Readable for RouteParameters {
767 fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
768 _init_and_read_len_prefixed_tlv_fields!(reader, {
769 (0, payment_params, (required: ReadableArgs, 0)),
770 (1, max_total_routing_fee_msat, option),
771 (2, final_value_msat, required),
772 (4, final_cltv_delta, option),
773 });
774 let mut payment_params: PaymentParameters = payment_params.0.unwrap();
775 if let Payee::Clear { ref mut final_cltv_expiry_delta, .. } = payment_params.payee {
776 if final_cltv_expiry_delta == &0 {
777 *final_cltv_expiry_delta = final_cltv_delta.ok_or(DecodeError::InvalidValue)?;
778 }
779 }
780 Ok(Self {
781 payment_params,
782 final_value_msat: final_value_msat.0.unwrap(),
783 max_total_routing_fee_msat,
784 })
785 }
786}
787
788pub const DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA: u32 = 1008;
790
791pub const DEFAULT_MAX_PATH_COUNT: u8 = 10;
795
796const DEFAULT_MAX_CHANNEL_SATURATION_POW_HALF: u8 = 2;
797
798const MEDIAN_HOP_CLTV_EXPIRY_DELTA: u32 = 40;
800
801pub const MAX_PATH_LENGTH_ESTIMATE: u8 = 19;
815
816#[derive(Clone, Debug, Hash, PartialEq, Eq)]
818pub struct PaymentParameters {
819 pub payee: Payee,
821
822 pub expiry_time: Option<u64>,
824
825 pub max_total_cltv_expiry_delta: u32,
828
829 pub max_path_count: u8,
832
833 pub max_path_length: u8,
836
837 pub max_channel_saturation_power_of_half: u8,
851
852 pub previously_failed_channels: Vec<u64>,
856
857 pub previously_failed_blinded_path_idxs: Vec<u64>,
861}
862
863impl Writeable for PaymentParameters {
864 #[rustfmt::skip]
865 fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
866 let mut clear_hints = &vec![];
867 let mut blinded_hints = None;
868 match &self.payee {
869 Payee::Clear { route_hints, .. } => clear_hints = route_hints,
870 Payee::Blinded { route_hints, .. } => {
871 let hints_iter = route_hints.iter().map(|path| (&path.payinfo, path.inner_blinded_path()));
872 blinded_hints = Some(crate::util::ser::IterableOwned(hints_iter));
873 }
874 }
875 write_tlv_fields!(writer, {
876 (0, self.payee.node_id(), option),
877 (1, self.max_total_cltv_expiry_delta, required),
878 (2, self.payee.features(), option),
879 (3, self.max_path_count, required),
880 (4, *clear_hints, required_vec),
881 (5, self.max_channel_saturation_power_of_half, required),
882 (6, self.expiry_time, option),
883 (7, self.previously_failed_channels, required_vec),
884 (8, blinded_hints, option),
885 (9, self.payee.final_cltv_expiry_delta(), option),
886 (11, self.previously_failed_blinded_path_idxs, required_vec),
887 (13, self.max_path_length, required),
888 });
889 Ok(())
890 }
891}
892
893impl ReadableArgs<u32> for PaymentParameters {
894 #[rustfmt::skip]
895 fn read<R: io::Read>(reader: &mut R, default_final_cltv_expiry_delta: u32) -> Result<Self, DecodeError> {
896 _init_and_read_len_prefixed_tlv_fields!(reader, {
897 (0, payee_pubkey, option),
898 (1, max_total_cltv_expiry_delta, (default_value, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA)),
899 (2, features, (option: ReadableArgs, payee_pubkey.is_some())),
900 (3, max_path_count, (default_value, DEFAULT_MAX_PATH_COUNT)),
901 (4, clear_route_hints, required_vec),
902 (5, max_channel_saturation_power_of_half, (default_value, DEFAULT_MAX_CHANNEL_SATURATION_POW_HALF)),
903 (6, expiry_time, option),
904 (7, previously_failed_channels, optional_vec),
905 (8, blinded_route_hints, optional_vec),
906 (9, final_cltv_expiry_delta, (default_value, default_final_cltv_expiry_delta)),
907 (11, previously_failed_blinded_path_idxs, optional_vec),
908 (13, max_path_length, (default_value, MAX_PATH_LENGTH_ESTIMATE)),
909 });
910 let blinded_route_hints = blinded_route_hints.unwrap_or(vec![]);
911 let payee = if blinded_route_hints.len() != 0 {
912 if clear_route_hints.len() != 0 || payee_pubkey.is_some() { return Err(DecodeError::InvalidValue) }
913 Payee::Blinded {
914 route_hints: blinded_route_hints
915 .into_iter()
916 .map(|(payinfo, path)| BlindedPaymentPath::from_parts(path, payinfo))
917 .collect(),
918 features: features.and_then(|f: Features| f.bolt12()),
919 }
920 } else {
921 Payee::Clear {
922 route_hints: clear_route_hints,
923 node_id: payee_pubkey.ok_or(DecodeError::InvalidValue)?,
924 features: features.and_then(|f| f.bolt11()),
925 final_cltv_expiry_delta: final_cltv_expiry_delta.0.unwrap(),
926 }
927 };
928 Ok(Self {
929 max_total_cltv_expiry_delta: _init_tlv_based_struct_field!(max_total_cltv_expiry_delta, (default_value, unused)),
930 max_path_count: _init_tlv_based_struct_field!(max_path_count, (default_value, unused)),
931 payee,
932 max_channel_saturation_power_of_half: _init_tlv_based_struct_field!(max_channel_saturation_power_of_half, (default_value, unused)),
933 expiry_time,
934 previously_failed_channels: previously_failed_channels.unwrap_or(Vec::new()),
935 previously_failed_blinded_path_idxs: previously_failed_blinded_path_idxs.unwrap_or(Vec::new()),
936 max_path_length: _init_tlv_based_struct_field!(max_path_length, (default_value, unused)),
937 })
938 }
939}
940
941impl PaymentParameters {
942 #[rustfmt::skip]
947 pub fn from_node_id(payee_pubkey: PublicKey, final_cltv_expiry_delta: u32) -> Self {
948 Self {
949 payee: Payee::Clear { node_id: payee_pubkey, route_hints: vec![], features: None, final_cltv_expiry_delta },
950 expiry_time: None,
951 max_total_cltv_expiry_delta: DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA,
952 max_path_count: DEFAULT_MAX_PATH_COUNT,
953 max_path_length: MAX_PATH_LENGTH_ESTIMATE,
954 max_channel_saturation_power_of_half: DEFAULT_MAX_CHANNEL_SATURATION_POW_HALF,
955 previously_failed_channels: Vec::new(),
956 previously_failed_blinded_path_idxs: Vec::new(),
957 }
958 }
959
960 #[rustfmt::skip]
972 pub fn for_keysend(payee_pubkey: PublicKey, final_cltv_expiry_delta: u32, allow_mpp: bool) -> Self {
973 Self::from_node_id(payee_pubkey, final_cltv_expiry_delta)
974 .with_bolt11_features(Bolt11InvoiceFeatures::for_keysend(allow_mpp))
975 .expect("PaymentParameters::from_node_id should always initialize the payee as unblinded")
976 }
977
978 pub fn from_bolt11_invoice(invoice: &Bolt11Invoice) -> Self {
982 let mut payment_params = Self::from_node_id(
983 invoice.recover_payee_pub_key(),
984 invoice.min_final_cltv_expiry_delta() as u32,
985 )
986 .with_route_hints(invoice.route_hints())
987 .unwrap();
988
989 if let Some(expiry) = invoice.expires_at() {
990 payment_params = payment_params.with_expiry_time(expiry.as_secs());
991 }
992 if let Some(features) = invoice.features() {
993 payment_params = payment_params.with_bolt11_features(features.clone()).unwrap();
994 }
995
996 payment_params
997 }
998
999 #[rustfmt::skip]
1003 pub fn from_bolt12_invoice(invoice: &Bolt12Invoice) -> Self {
1004 Self::blinded(invoice.payment_paths().to_vec())
1005 .with_bolt12_features(invoice.invoice_features().clone()).unwrap()
1006 .with_expiry_time(invoice.created_at().as_secs().saturating_add(invoice.relative_expiry().as_secs()))
1007 }
1008
1009 #[rustfmt::skip]
1013 pub fn from_static_invoice(invoice: &StaticInvoice) -> Self {
1014 Self::blinded(invoice.payment_paths().to_vec())
1015 .with_bolt12_features(invoice.invoice_features().clone()).unwrap()
1016 .with_expiry_time(invoice.created_at().as_secs().saturating_add(invoice.relative_expiry().as_secs()))
1017 }
1018
1019 pub fn blinded(blinded_route_hints: Vec<BlindedPaymentPath>) -> Self {
1021 Self {
1022 payee: Payee::Blinded { route_hints: blinded_route_hints, features: None },
1023 expiry_time: None,
1024 max_total_cltv_expiry_delta: DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA,
1025 max_path_count: DEFAULT_MAX_PATH_COUNT,
1026 max_path_length: MAX_PATH_LENGTH_ESTIMATE,
1027 max_channel_saturation_power_of_half: DEFAULT_MAX_CHANNEL_SATURATION_POW_HALF,
1028 previously_failed_channels: Vec::new(),
1029 previously_failed_blinded_path_idxs: Vec::new(),
1030 }
1031 }
1032
1033 #[rustfmt::skip]
1040 pub(crate) fn with_user_config_ignoring_fee_limit(self, params_config: RouteParametersConfig) -> Self {
1041 Self {
1042 max_total_cltv_expiry_delta: params_config.max_total_cltv_expiry_delta,
1043 max_path_count: params_config.max_path_count,
1044 max_channel_saturation_power_of_half: params_config.max_channel_saturation_power_of_half,
1045 ..self
1046 }
1047 }
1048
1049 #[rustfmt::skip]
1054 pub fn with_bolt12_features(self, features: Bolt12InvoiceFeatures) -> Result<Self, ()> {
1055 match self.payee {
1056 Payee::Clear { .. } => Err(()),
1057 Payee::Blinded { route_hints, .. } =>
1058 Ok(Self { payee: Payee::Blinded { route_hints, features: Some(features) }, ..self })
1059 }
1060 }
1061
1062 #[rustfmt::skip]
1067 pub fn with_bolt11_features(self, features: Bolt11InvoiceFeatures) -> Result<Self, ()> {
1068 match self.payee {
1069 Payee::Blinded { .. } => Err(()),
1070 Payee::Clear { route_hints, node_id, final_cltv_expiry_delta, .. } =>
1071 Ok(Self {
1072 payee: Payee::Clear {
1073 route_hints, node_id, features: Some(features), final_cltv_expiry_delta
1074 }, ..self
1075 })
1076 }
1077 }
1078
1079 #[rustfmt::skip]
1084 pub fn with_route_hints(self, route_hints: Vec<RouteHint>) -> Result<Self, ()> {
1085 match self.payee {
1086 Payee::Blinded { .. } => Err(()),
1087 Payee::Clear { node_id, features, final_cltv_expiry_delta, .. } =>
1088 Ok(Self {
1089 payee: Payee::Clear {
1090 route_hints, node_id, features, final_cltv_expiry_delta,
1091 }, ..self
1092 })
1093 }
1094 }
1095
1096 pub fn with_expiry_time(self, expiry_time: u64) -> Self {
1100 Self { expiry_time: Some(expiry_time), ..self }
1101 }
1102
1103 pub fn with_max_total_cltv_expiry_delta(self, max_total_cltv_expiry_delta: u32) -> Self {
1107 Self { max_total_cltv_expiry_delta, ..self }
1108 }
1109
1110 pub fn with_max_path_count(self, max_path_count: u8) -> Self {
1114 Self { max_path_count, ..self }
1115 }
1116
1117 pub fn with_max_channel_saturation_power_of_half(
1122 self, max_channel_saturation_power_of_half: u8,
1123 ) -> Self {
1124 Self { max_channel_saturation_power_of_half, ..self }
1125 }
1126
1127 #[rustfmt::skip]
1128 pub(crate) fn insert_previously_failed_blinded_path(&mut self, failed_blinded_tail: &BlindedTail) {
1129 let mut found_blinded_tail = false;
1130 for (idx, path) in self.payee.blinded_route_hints().iter().enumerate() {
1131 if &failed_blinded_tail.hops == path.blinded_hops() &&
1132 failed_blinded_tail.blinding_point == path.blinding_point()
1133 {
1134 self.previously_failed_blinded_path_idxs.push(idx as u64);
1135 found_blinded_tail = true;
1136 }
1137 }
1138 debug_assert!(found_blinded_tail);
1139 }
1140}
1141
1142#[derive(Clone, Copy, Debug)]
1144pub struct RouteParametersConfig {
1145 pub max_total_routing_fee_msat: Option<u64>,
1154
1155 pub max_total_cltv_expiry_delta: u32,
1158
1159 pub max_path_count: u8,
1162
1163 pub max_channel_saturation_power_of_half: u8,
1177}
1178
1179impl_writeable_tlv_based!(RouteParametersConfig, {
1180 (1, max_total_routing_fee_msat, option),
1181 (3, max_total_cltv_expiry_delta, required),
1182 (5, max_path_count, required),
1183 (7, max_channel_saturation_power_of_half, required),
1184});
1185
1186impl RouteParametersConfig {
1187 pub fn with_max_total_routing_fee_msat(self, fee_msat: u64) -> Self {
1191 Self { max_total_routing_fee_msat: Some(fee_msat), ..self }
1192 }
1193
1194 pub fn with_max_total_cltv_expiry_delta(self, max_total_cltv_expiry_delta: u32) -> Self {
1198 Self { max_total_cltv_expiry_delta, ..self }
1199 }
1200
1201 pub fn with_max_path_count(self, max_path_count: u8) -> Self {
1205 Self { max_path_count, ..self }
1206 }
1207
1208 pub fn with_max_channel_saturation_power_of_half(
1213 self, max_channel_saturation_power_of_half: u8,
1214 ) -> Self {
1215 Self { max_channel_saturation_power_of_half, ..self }
1216 }
1217}
1218
1219impl Default for RouteParametersConfig {
1220 fn default() -> Self {
1222 Self {
1223 max_total_routing_fee_msat: None,
1224 max_total_cltv_expiry_delta: DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA,
1225 max_path_count: DEFAULT_MAX_PATH_COUNT,
1226 max_channel_saturation_power_of_half: DEFAULT_MAX_CHANNEL_SATURATION_POW_HALF,
1227 }
1228 }
1229}
1230
1231#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1234pub enum Payee {
1235 Blinded {
1238 route_hints: Vec<BlindedPaymentPath>,
1241 features: Option<Bolt12InvoiceFeatures>,
1246 },
1247 Clear {
1249 node_id: PublicKey,
1251 route_hints: Vec<RouteHint>,
1253 features: Option<Bolt11InvoiceFeatures>,
1260 final_cltv_expiry_delta: u32,
1262 },
1263}
1264
1265impl Payee {
1266 fn node_id(&self) -> Option<PublicKey> {
1267 match self {
1268 Self::Clear { node_id, .. } => Some(*node_id),
1269 _ => None,
1270 }
1271 }
1272 fn node_features(&self) -> Option<NodeFeatures> {
1273 match self {
1274 Self::Clear { features, .. } => features.as_ref().map(|f| f.to_context()),
1275 Self::Blinded { features, .. } => features.as_ref().map(|f| f.to_context()),
1276 }
1277 }
1278 #[rustfmt::skip]
1279 fn supports_basic_mpp(&self) -> bool {
1280 match self {
1281 Self::Clear { features, .. } => features.as_ref().map_or(false, |f| f.supports_basic_mpp()),
1282 Self::Blinded { features, .. } => features.as_ref().map_or(false, |f| f.supports_basic_mpp()),
1283 }
1284 }
1285 fn features(&self) -> Option<FeaturesRef<'_>> {
1286 match self {
1287 Self::Clear { features, .. } => features.as_ref().map(|f| FeaturesRef::Bolt11(f)),
1288 Self::Blinded { features, .. } => features.as_ref().map(|f| FeaturesRef::Bolt12(f)),
1289 }
1290 }
1291 fn final_cltv_expiry_delta(&self) -> Option<u32> {
1292 match self {
1293 Self::Clear { final_cltv_expiry_delta, .. } => Some(*final_cltv_expiry_delta),
1294 _ => None,
1295 }
1296 }
1297 #[rustfmt::skip]
1298 pub(crate) fn blinded_route_hints(&self) -> &[BlindedPaymentPath] {
1299 match self {
1300 Self::Blinded { route_hints, .. } => &route_hints[..],
1301 Self::Clear { .. } => &[]
1302 }
1303 }
1304
1305 #[rustfmt::skip]
1306 pub(crate) fn blinded_route_hints_mut(&mut self) -> &mut [BlindedPaymentPath] {
1307 match self {
1308 Self::Blinded { route_hints, .. } => &mut route_hints[..],
1309 Self::Clear { .. } => &mut []
1310 }
1311 }
1312
1313 #[rustfmt::skip]
1314 fn unblinded_route_hints(&self) -> &[RouteHint] {
1315 match self {
1316 Self::Blinded { .. } => &[],
1317 Self::Clear { route_hints, .. } => &route_hints[..]
1318 }
1319 }
1320}
1321
1322enum FeaturesRef<'a> {
1323 Bolt11(&'a Bolt11InvoiceFeatures),
1324 Bolt12(&'a Bolt12InvoiceFeatures),
1325}
1326enum Features {
1327 Bolt11(Bolt11InvoiceFeatures),
1328 Bolt12(Bolt12InvoiceFeatures),
1329}
1330
1331impl Features {
1332 fn bolt12(self) -> Option<Bolt12InvoiceFeatures> {
1333 match self {
1334 Self::Bolt12(f) => Some(f),
1335 _ => None,
1336 }
1337 }
1338 fn bolt11(self) -> Option<Bolt11InvoiceFeatures> {
1339 match self {
1340 Self::Bolt11(f) => Some(f),
1341 _ => None,
1342 }
1343 }
1344}
1345
1346impl<'a> Writeable for FeaturesRef<'a> {
1347 fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
1348 match self {
1349 Self::Bolt11(f) => Ok(f.write(w)?),
1350 Self::Bolt12(f) => Ok(f.write(w)?),
1351 }
1352 }
1353}
1354
1355impl ReadableArgs<bool> for Features {
1356 #[rustfmt::skip]
1357 fn read<R: io::Read>(reader: &mut R, bolt11: bool) -> Result<Self, DecodeError> {
1358 if bolt11 { return Ok(Self::Bolt11(Readable::read(reader)?)) }
1359 Ok(Self::Bolt12(Readable::read(reader)?))
1360 }
1361}
1362
1363impl Writeable for RouteHint {
1364 fn write<W: crate::util::ser::Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
1365 (self.0.len() as u64).write(writer)?;
1366 for hop in self.0.iter() {
1367 hop.write(writer)?;
1368 }
1369 Ok(())
1370 }
1371}
1372
1373impl Readable for RouteHint {
1374 fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
1375 let hop_count: u64 = Readable::read(reader)?;
1376 let mut hops = Vec::with_capacity(cmp::min(hop_count, 16) as usize);
1377 for _ in 0..hop_count {
1378 hops.push(Readable::read(reader)?);
1379 }
1380 Ok(Self(hops))
1381 }
1382}
1383
1384impl_writeable_tlv_based!(RouteHintHop, {
1385 (0, src_node_id, required),
1386 (1, htlc_minimum_msat, option),
1387 (2, short_channel_id, required),
1388 (3, htlc_maximum_msat, option),
1389 (4, fees, required),
1390 (6, cltv_expiry_delta, required),
1391});
1392
1393#[derive(Eq, PartialEq)]
1394#[repr(align(32))] struct RouteGraphNode {
1396 node_counter: u32,
1397 score: u128,
1398 value_contribution_msat: u64,
1404 total_cltv_delta: u16,
1405 path_length_to_node: u8,
1407}
1408
1409impl cmp::Ord for RouteGraphNode {
1410 #[rustfmt::skip]
1411 fn cmp(&self, other: &RouteGraphNode) -> cmp::Ordering {
1412 other.score.cmp(&self.score)
1413 .then_with(|| self.value_contribution_msat.cmp(&other.value_contribution_msat))
1414 .then_with(|| other.path_length_to_node.cmp(&self.path_length_to_node))
1415 .then_with(|| other.node_counter.cmp(&self.node_counter))
1416 }
1417}
1418
1419impl cmp::PartialOrd for RouteGraphNode {
1420 fn partial_cmp(&self, other: &RouteGraphNode) -> Option<cmp::Ordering> {
1421 Some(self.cmp(other))
1422 }
1423}
1424
1425const _GRAPH_NODE_32: () = assert!(core::mem::size_of::<RouteGraphNode>() == 32);
1428
1429#[derive(Clone, Debug)]
1431pub struct FirstHopCandidate<'a> {
1432 pub details: &'a ChannelDetails,
1441 pub payer_node_id: &'a NodeId,
1445 pub(crate) payer_node_counter: u32,
1452 pub(crate) target_node_counter: u32,
1459}
1460
1461#[derive(Clone, Debug)]
1463pub struct PublicHopCandidate<'a> {
1464 pub info: DirectedChannelInfo<'a>,
1469 pub short_channel_id: u64,
1472}
1473
1474#[derive(Clone, Debug)]
1476pub struct PrivateHopCandidate<'a> {
1477 pub hint: &'a RouteHintHop,
1481 pub target_node_id: &'a NodeId,
1485 pub(crate) source_node_counter: u32,
1492 pub(crate) target_node_counter: u32,
1499}
1500
1501#[derive(Clone, Debug)]
1503pub struct BlindedPathCandidate<'a> {
1504 pub source_node_id: &'a NodeId,
1509 pub hint: &'a BlindedPaymentPath,
1514 hint_idx: usize,
1519 source_node_counter: u32,
1526}
1527
1528#[derive(Clone, Debug)]
1530pub struct OneHopBlindedPathCandidate<'a> {
1531 pub source_node_id: &'a NodeId,
1536 pub hint: &'a BlindedPaymentPath,
1545 hint_idx: usize,
1550 source_node_counter: u32,
1557}
1558
1559#[derive(Clone, Debug)]
1564pub enum CandidateRouteHop<'a> {
1565 FirstHop(FirstHopCandidate<'a>),
1567 PublicHop(PublicHopCandidate<'a>),
1569 PrivateHop(PrivateHopCandidate<'a>),
1574 Blinded(BlindedPathCandidate<'a>),
1583 OneHopBlinded(OneHopBlindedPathCandidate<'a>),
1597}
1598
1599impl<'a> CandidateRouteHop<'a> {
1600 #[inline]
1616 fn short_channel_id(&self) -> Option<u64> {
1617 match self {
1618 CandidateRouteHop::FirstHop(hop) => hop.details.get_outbound_payment_scid(),
1619 CandidateRouteHop::PublicHop(hop) => Some(hop.short_channel_id),
1620 CandidateRouteHop::PrivateHop(hop) => Some(hop.hint.short_channel_id),
1621 CandidateRouteHop::Blinded(_) => None,
1622 CandidateRouteHop::OneHopBlinded(_) => None,
1623 }
1624 }
1625
1626 #[inline]
1632 #[rustfmt::skip]
1633 pub fn globally_unique_short_channel_id(&self) -> Option<u64> {
1634 match self {
1635 CandidateRouteHop::FirstHop(hop) => if hop.details.is_announced { hop.details.short_channel_id } else { None },
1636 CandidateRouteHop::PublicHop(hop) => Some(hop.short_channel_id),
1637 CandidateRouteHop::PrivateHop(_) => None,
1638 CandidateRouteHop::Blinded(_) => None,
1639 CandidateRouteHop::OneHopBlinded(_) => None,
1640 }
1641 }
1642
1643 fn features(&self) -> ChannelFeatures {
1645 match self {
1646 CandidateRouteHop::FirstHop(hop) => hop.details.counterparty.features.to_context(),
1647 CandidateRouteHop::PublicHop(hop) => hop.info.channel().features.clone(),
1648 CandidateRouteHop::PrivateHop(_) => ChannelFeatures::empty(),
1649 CandidateRouteHop::Blinded(_) => ChannelFeatures::empty(),
1650 CandidateRouteHop::OneHopBlinded(_) => ChannelFeatures::empty(),
1651 }
1652 }
1653
1654 #[inline]
1660 pub fn cltv_expiry_delta(&self) -> u32 {
1661 match self {
1662 CandidateRouteHop::FirstHop(_) => 0,
1663 CandidateRouteHop::PublicHop(hop) => hop.info.direction().cltv_expiry_delta as u32,
1664 CandidateRouteHop::PrivateHop(hop) => hop.hint.cltv_expiry_delta as u32,
1665 CandidateRouteHop::Blinded(hop) => hop.hint.payinfo.cltv_expiry_delta as u32,
1666 CandidateRouteHop::OneHopBlinded(_) => 0,
1667 }
1668 }
1669
1670 #[inline]
1672 pub fn htlc_minimum_msat(&self) -> u64 {
1673 match self {
1674 CandidateRouteHop::FirstHop(hop) => hop.details.next_outbound_htlc_minimum_msat,
1675 CandidateRouteHop::PublicHop(hop) => hop.info.direction().htlc_minimum_msat,
1676 CandidateRouteHop::PrivateHop(hop) => hop.hint.htlc_minimum_msat.unwrap_or(0),
1677 CandidateRouteHop::Blinded(hop) => hop.hint.payinfo.htlc_minimum_msat,
1678 CandidateRouteHop::OneHopBlinded { .. } => 0,
1679 }
1680 }
1681
1682 #[inline(always)]
1683 fn src_node_counter(&self) -> u32 {
1684 match self {
1685 CandidateRouteHop::FirstHop(hop) => hop.payer_node_counter,
1686 CandidateRouteHop::PublicHop(hop) => hop.info.source_counter(),
1687 CandidateRouteHop::PrivateHop(hop) => hop.source_node_counter,
1688 CandidateRouteHop::Blinded(hop) => hop.source_node_counter,
1689 CandidateRouteHop::OneHopBlinded(hop) => hop.source_node_counter,
1690 }
1691 }
1692
1693 #[inline]
1694 fn target_node_counter(&self) -> Option<u32> {
1695 match self {
1696 CandidateRouteHop::FirstHop(hop) => Some(hop.target_node_counter),
1697 CandidateRouteHop::PublicHop(hop) => Some(hop.info.target_counter()),
1698 CandidateRouteHop::PrivateHop(hop) => Some(hop.target_node_counter),
1699 CandidateRouteHop::Blinded(_) => None,
1700 CandidateRouteHop::OneHopBlinded(_) => None,
1701 }
1702 }
1703
1704 #[inline]
1706 #[rustfmt::skip]
1707 pub fn fees(&self) -> RoutingFees {
1708 match self {
1709 CandidateRouteHop::FirstHop(_) => RoutingFees {
1710 base_msat: 0, proportional_millionths: 0,
1711 },
1712 CandidateRouteHop::PublicHop(hop) => hop.info.direction().fees,
1713 CandidateRouteHop::PrivateHop(hop) => hop.hint.fees,
1714 CandidateRouteHop::Blinded(hop) => {
1715 RoutingFees {
1716 base_msat: hop.hint.payinfo.fee_base_msat,
1717 proportional_millionths: hop.hint.payinfo.fee_proportional_millionths
1718 }
1719 },
1720 CandidateRouteHop::OneHopBlinded(_) =>
1721 RoutingFees { base_msat: 0, proportional_millionths: 0 },
1722 }
1723 }
1724
1725 #[rustfmt::skip]
1730 fn effective_capacity(&self) -> EffectiveCapacity {
1731 match self {
1732 CandidateRouteHop::FirstHop(hop) => EffectiveCapacity::ExactLiquidity {
1733 liquidity_msat: hop.details.next_outbound_htlc_limit_msat,
1734 },
1735 CandidateRouteHop::PublicHop(hop) => hop.info.effective_capacity(),
1736 CandidateRouteHop::PrivateHop(PrivateHopCandidate { hint: RouteHintHop { htlc_maximum_msat: Some(max), .. }, .. }) =>
1737 EffectiveCapacity::HintMaxHTLC { amount_msat: *max },
1738 CandidateRouteHop::PrivateHop(PrivateHopCandidate { hint: RouteHintHop { htlc_maximum_msat: None, .. }, .. }) =>
1739 EffectiveCapacity::Infinite,
1740 CandidateRouteHop::Blinded(hop) =>
1741 EffectiveCapacity::HintMaxHTLC { amount_msat: hop.hint.payinfo.htlc_maximum_msat },
1742 CandidateRouteHop::OneHopBlinded(_) => EffectiveCapacity::Infinite,
1743 }
1744 }
1745
1746 #[inline]
1750 #[rustfmt::skip]
1751 fn id(&self) -> CandidateHopId {
1752 match self {
1753 CandidateRouteHop::Blinded(hop) => CandidateHopId::Blinded(hop.hint_idx),
1754 CandidateRouteHop::OneHopBlinded(hop) => CandidateHopId::Blinded(hop.hint_idx),
1755 _ => CandidateHopId::Clear((self.short_channel_id().unwrap(), self.source() < self.target().unwrap())),
1756 }
1757 }
1758 #[rustfmt::skip]
1759 fn blinded_path(&self) -> Option<&'a BlindedPaymentPath> {
1760 match self {
1761 CandidateRouteHop::Blinded(BlindedPathCandidate { hint, .. }) | CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { hint, .. }) => {
1762 Some(&hint)
1763 },
1764 _ => None,
1765 }
1766 }
1767 #[rustfmt::skip]
1768 fn blinded_hint_idx(&self) -> Option<usize> {
1769 match self {
1770 Self::Blinded(BlindedPathCandidate { hint_idx, .. }) |
1771 Self::OneHopBlinded(OneHopBlindedPathCandidate { hint_idx, .. }) => {
1772 Some(*hint_idx)
1773 },
1774 _ => None,
1775 }
1776 }
1777 #[inline]
1783 pub fn source(&self) -> NodeId {
1784 match self {
1785 CandidateRouteHop::FirstHop(hop) => *hop.payer_node_id,
1786 CandidateRouteHop::PublicHop(hop) => *hop.info.source(),
1787 CandidateRouteHop::PrivateHop(hop) => hop.hint.src_node_id.into(),
1788 CandidateRouteHop::Blinded(hop) => *hop.source_node_id,
1789 CandidateRouteHop::OneHopBlinded(hop) => *hop.source_node_id,
1790 }
1791 }
1792 #[inline]
1802 pub fn target(&self) -> Option<NodeId> {
1803 match self {
1804 CandidateRouteHop::FirstHop(hop) => Some(hop.details.counterparty.node_id.into()),
1805 CandidateRouteHop::PublicHop(hop) => Some(*hop.info.target()),
1806 CandidateRouteHop::PrivateHop(hop) => Some(*hop.target_node_id),
1807 CandidateRouteHop::Blinded(_) => None,
1808 CandidateRouteHop::OneHopBlinded(_) => None,
1809 }
1810 }
1811}
1812
1813#[derive(Clone, Copy, Eq, Hash, Ord, PartialOrd, PartialEq)]
1823enum CandidateHopId {
1824 Clear((u64, bool)),
1826 Blinded(usize),
1828}
1829
1830struct NodeCounters<'a> {
1850 network_graph: &'a ReadOnlyNetworkGraph<'a>,
1851 private_node_id_to_node_counter: HashMap<NodeId, u32>,
1852 private_hop_key_cache: HashMap<PublicKey, (NodeId, u32)>,
1853}
1854
1855struct NodeCountersBuilder<'a>(NodeCounters<'a>);
1856
1857impl<'a> NodeCountersBuilder<'a> {
1858 fn new(network_graph: &'a ReadOnlyNetworkGraph) -> Self {
1859 Self(NodeCounters {
1860 network_graph,
1861 private_node_id_to_node_counter: new_hash_map(),
1862 private_hop_key_cache: new_hash_map(),
1863 })
1864 }
1865
1866 fn select_node_counter_for_pubkey(&mut self, pubkey: PublicKey) -> u32 {
1867 let id = NodeId::from_pubkey(&pubkey);
1868 let counter = self.select_node_counter_for_id(id);
1869 self.0.private_hop_key_cache.insert(pubkey, (id, counter));
1870 counter
1871 }
1872
1873 #[rustfmt::skip]
1874 fn select_node_counter_for_id(&mut self, node_id: NodeId) -> u32 {
1875 self.0.network_graph.nodes().get(&node_id)
1878 .map(|node| node.node_counter)
1879 .unwrap_or_else(|| {
1880 let next_node_counter = self.0.network_graph.max_node_counter() + 1 +
1881 self.0.private_node_id_to_node_counter.len() as u32;
1882 *self.0.private_node_id_to_node_counter.entry(node_id).or_insert(next_node_counter)
1883 })
1884 }
1885
1886 #[rustfmt::skip]
1887 fn build(self) -> NodeCounters<'a> { self.0 }
1888}
1889
1890impl<'a> NodeCounters<'a> {
1891 #[rustfmt::skip]
1892 fn max_counter(&self) -> u32 {
1893 self.network_graph.max_node_counter() +
1894 self.private_node_id_to_node_counter.len() as u32
1895 }
1896
1897 fn private_node_counter_from_pubkey(&self, pubkey: &PublicKey) -> Option<&(NodeId, u32)> {
1898 self.private_hop_key_cache.get(pubkey)
1899 }
1900
1901 #[rustfmt::skip]
1902 fn node_counter_from_id(&self, node_id: &NodeId) -> Option<(&NodeId, u32)> {
1903 self.private_node_id_to_node_counter.get_key_value(node_id).map(|(a, b)| (a, *b))
1904 .or_else(|| {
1905 self.network_graph.nodes().get_key_value(node_id)
1906 .map(|(node_id, node)| (node_id, node.node_counter))
1907 })
1908 }
1909}
1910
1911#[rustfmt::skip]
1914fn calculate_blinded_path_intro_points<'a, L: Deref>(
1915 payment_params: &PaymentParameters, node_counters: &'a NodeCounters,
1916 network_graph: &ReadOnlyNetworkGraph, logger: &L, our_node_id: NodeId,
1917 first_hop_targets: &HashMap<NodeId, (Vec<&ChannelDetails>, u32)>,
1918) -> Result<Vec<Option<(&'a NodeId, u32)>>, &'static str>
1919where L::Target: Logger {
1920 let introduction_node_id_cache = payment_params.payee.blinded_route_hints().iter()
1921 .map(|path| {
1922 match path.introduction_node() {
1923 IntroductionNode::NodeId(pubkey) => {
1924 node_counters.node_counter_from_id(&NodeId::from_pubkey(&pubkey))
1927 },
1928 IntroductionNode::DirectedShortChannelId(direction, scid) => {
1929 path.public_introduction_node_id(network_graph)
1930 .map(|node_id_ref| *node_id_ref)
1931 .or_else(|| {
1932 first_hop_targets.iter().find(|(_, (channels, _))|
1933 channels
1934 .iter()
1935 .any(|details| Some(*scid) == details.get_outbound_payment_scid())
1936 ).map(|(cp, _)| direction.select_node_id(our_node_id, *cp))
1937 })
1938 .and_then(|node_id| node_counters.node_counter_from_id(&node_id))
1939 },
1940 }
1941 })
1942 .collect::<Vec<_>>();
1943 match &payment_params.payee {
1944 Payee::Clear { route_hints, node_id, .. } => {
1945 for route in route_hints.iter() {
1946 for hop in &route.0 {
1947 if hop.src_node_id == *node_id {
1948 return Err("Route hint cannot have the payee as the source.");
1949 }
1950 }
1951 }
1952 },
1953 Payee::Blinded { route_hints, .. } => {
1954 if introduction_node_id_cache.iter().all(|info_opt| info_opt.map(|(a, _)| a) == Some(&our_node_id)) {
1955 return Err("Cannot generate a route to blinded paths if we are the introduction node to all of them");
1956 }
1957 for (blinded_path, info_opt) in route_hints.iter().zip(introduction_node_id_cache.iter()) {
1958 if blinded_path.blinded_hops().len() == 0 {
1959 return Err("0-hop blinded path provided");
1960 }
1961 let introduction_node_id = match info_opt {
1962 None => continue,
1963 Some(info) => info.0,
1964 };
1965 if *introduction_node_id == our_node_id {
1966 log_info!(logger, "Got blinded path with ourselves as the introduction node, ignoring");
1967 } else if blinded_path.blinded_hops().len() == 1 &&
1968 route_hints
1969 .iter().zip(introduction_node_id_cache.iter())
1970 .filter(|(p, _)| p.blinded_hops().len() == 1)
1971 .any(|(_, iter_info_opt)| iter_info_opt.is_some() && iter_info_opt != info_opt)
1972 {
1973 return Err("1-hop blinded paths must all have matching introduction node ids");
1974 }
1975 }
1976 }
1977 }
1978
1979 Ok(introduction_node_id_cache)
1980}
1981
1982#[inline]
1983#[rustfmt::skip]
1984fn max_htlc_from_capacity(capacity: EffectiveCapacity, max_channel_saturation_power_of_half: u8) -> u64 {
1985 let saturation_shift: u32 = max_channel_saturation_power_of_half as u32;
1986 match capacity {
1987 EffectiveCapacity::ExactLiquidity { liquidity_msat } => liquidity_msat,
1988 EffectiveCapacity::Infinite => u64::max_value(),
1989 EffectiveCapacity::Unknown => EffectiveCapacity::Unknown.as_msat(),
1990 EffectiveCapacity::AdvertisedMaxHTLC { amount_msat } =>
1991 amount_msat.checked_shr(saturation_shift).unwrap_or(0),
1992 EffectiveCapacity::HintMaxHTLC { amount_msat } => amount_msat,
1995 EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat } =>
1996 cmp::min(capacity_msat.checked_shr(saturation_shift).unwrap_or(0), htlc_maximum_msat),
1997 }
1998}
1999
2000#[rustfmt::skip]
2001fn iter_equal<I1: Iterator, I2: Iterator>(mut iter_a: I1, mut iter_b: I2)
2002-> bool where I1::Item: PartialEq<I2::Item> {
2003 loop {
2004 let a = iter_a.next();
2005 let b = iter_b.next();
2006 if a.is_none() && b.is_none() { return true; }
2007 if a.is_none() || b.is_none() { return false; }
2008 if a.unwrap().ne(&b.unwrap()) { return false; }
2009 }
2010}
2011
2012#[derive(Clone)]
2017#[repr(align(128))]
2018struct PathBuildingHop<'a> {
2019 candidate: CandidateRouteHop<'a>,
2020 was_processed: bool,
2026 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
2031 best_path_from_hop_selected: bool,
2032 is_first_hop_target: bool,
2040 is_last_hop_target: bool,
2042 total_fee_msat: u64,
2047 path_htlc_minimum_msat: u64,
2050 path_penalty_msat: u64,
2053
2054 fee_msat: u64,
2055
2056 next_hops_fee_msat: u64,
2058 hop_use_fee_msat: u64,
2061
2062 value_contribution_msat: u64,
2064}
2065
2066const _NODE_MAP_SIZE_TWO_CACHE_LINES: usize = 128 - core::mem::size_of::<Option<PathBuildingHop>>();
2067const _NODE_MAP_SIZE_EXACTLY_TWO_CACHE_LINES: usize =
2068 core::mem::size_of::<Option<PathBuildingHop>>() - 128;
2069
2070impl<'a> core::fmt::Debug for PathBuildingHop<'a> {
2071 #[rustfmt::skip]
2072 fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
2073 let mut debug_struct = f.debug_struct("PathBuildingHop");
2074 debug_struct
2075 .field("source_node_id", &self.candidate.source())
2076 .field("target_node_id", &self.candidate.target())
2077 .field("short_channel_id", &self.candidate.short_channel_id())
2078 .field("is_first_hop_target", &self.is_first_hop_target)
2079 .field("is_last_hop_target", &self.is_last_hop_target)
2080 .field("total_fee_msat", &self.total_fee_msat)
2081 .field("next_hops_fee_msat", &self.next_hops_fee_msat)
2082 .field("hop_use_fee_msat", &self.hop_use_fee_msat)
2083 .field("total_fee_msat - (next_hops_fee_msat + hop_use_fee_msat)", &(&self.total_fee_msat.saturating_sub(self.next_hops_fee_msat).saturating_sub(self.hop_use_fee_msat)))
2084 .field("path_penalty_msat", &self.path_penalty_msat)
2085 .field("path_htlc_minimum_msat", &self.path_htlc_minimum_msat)
2086 .field("cltv_expiry_delta", &self.candidate.cltv_expiry_delta())
2087 .field("value_contribution_msat", &self.value_contribution_msat);
2088 debug_struct.finish()
2089 }
2090}
2091
2092#[derive(Clone)]
2095struct PaymentPath<'a> {
2096 hops: Vec<(PathBuildingHop<'a>, NodeFeatures)>,
2097}
2098
2099impl<'a> PaymentPath<'a> {
2100 fn get_value_msat(&self) -> u64 {
2102 self.hops.last().unwrap().0.fee_msat
2103 }
2104
2105 fn get_path_penalty_msat(&self) -> u64 {
2106 self.hops.first().map(|h| h.0.path_penalty_msat).unwrap_or(u64::max_value())
2107 }
2108
2109 fn get_total_fee_paid_msat(&self) -> u64 {
2110 if self.hops.len() < 1 {
2111 return 0;
2112 }
2113 let mut result = 0;
2114 for (i, (hop, _)) in self.hops.iter().enumerate() {
2116 if i != self.hops.len() - 1 {
2117 result += hop.fee_msat;
2118 }
2119 }
2120 return result;
2121 }
2122
2123 fn get_cost_per_msat(&self) -> u128 {
2126 let fee_cost = self.get_cost_msat();
2127 let value_msat = self.get_value_msat();
2128 debug_assert!(value_msat > 0, "Paths should always send more than 0 msat");
2129 if fee_cost == u64::MAX || value_msat == 0 {
2130 u64::MAX.into()
2131 } else {
2132 ((fee_cost as u128) << 64) / value_msat as u128
2135 }
2136 }
2137
2138 fn get_cost_msat(&self) -> u64 {
2140 self.get_total_fee_paid_msat().saturating_add(self.get_path_penalty_msat())
2141 }
2142
2143 #[rustfmt::skip]
2158 fn update_value_and_recompute_fees(&mut self, value_msat: u64) -> u64 {
2159 let mut extra_contribution_msat = 0;
2160 let mut total_fee_paid_msat = 0 as u64;
2161 for i in (0..self.hops.len()).rev() {
2162 let last_hop = i == self.hops.len() - 1;
2163
2164 let mut cur_hop_fees_msat = 0;
2168 if !last_hop {
2169 cur_hop_fees_msat = self.hops.get(i + 1).unwrap().0.hop_use_fee_msat;
2170 }
2171
2172 let cur_hop = &mut self.hops.get_mut(i).unwrap().0;
2173 cur_hop.next_hops_fee_msat = total_fee_paid_msat;
2174 cur_hop.path_penalty_msat += extra_contribution_msat;
2175 let mut cur_hop_transferred_amount_msat = total_fee_paid_msat + value_msat;
2180 if let Some(extra_fees_msat) = cur_hop.candidate.htlc_minimum_msat().checked_sub(cur_hop_transferred_amount_msat) {
2181 cur_hop_transferred_amount_msat += extra_fees_msat;
2190
2191 if last_hop {
2194 extra_contribution_msat = extra_fees_msat;
2195 } else {
2196 total_fee_paid_msat += extra_fees_msat;
2197 cur_hop_fees_msat += extra_fees_msat;
2198 }
2199 }
2200
2201 if last_hop {
2202 cur_hop.fee_msat = cur_hop_transferred_amount_msat;
2205 } else {
2206 cur_hop.fee_msat = cur_hop_fees_msat;
2209 }
2210
2211 if i != 0 {
2215 if let Some(new_fee) = compute_fees(cur_hop_transferred_amount_msat, cur_hop.candidate.fees()) {
2216 cur_hop.hop_use_fee_msat = new_fee;
2217 total_fee_paid_msat += new_fee;
2218 } else {
2219 unreachable!();
2224 }
2225 }
2226 }
2227 value_msat + extra_contribution_msat
2228 }
2229
2230 #[rustfmt::skip]
2235 fn max_final_value_msat(
2236 &self, used_liquidities: &HashMap<CandidateHopId, u64>, channel_saturation_pow_half: u8
2237 ) -> (usize, u64) {
2238 let mut max_path_contribution = (0, u64::MAX);
2239 for (idx, (hop, _)) in self.hops.iter().enumerate() {
2240 let hop_effective_capacity_msat = hop.candidate.effective_capacity();
2241 let hop_max_msat = max_htlc_from_capacity(
2242 hop_effective_capacity_msat, channel_saturation_pow_half
2243 ).saturating_sub(*used_liquidities.get(&hop.candidate.id()).unwrap_or(&0_u64));
2244
2245 let next_hops_feerates_iter = self.hops
2246 .iter()
2247 .skip(idx + 1)
2248 .map(|(hop, _)| hop.candidate.fees());
2249
2250 let (next_hops_aggregated_base, next_hops_aggregated_prop) =
2253 crate::blinded_path::payment::compute_aggregated_base_prop_fee(next_hops_feerates_iter).unwrap();
2254
2255 let hop_max_final_value_contribution = (hop_max_msat as u128)
2257 .checked_sub(next_hops_aggregated_base as u128)
2258 .and_then(|f| f.checked_mul(1_000_000))
2259 .and_then(|f| f.checked_add(next_hops_aggregated_prop as u128))
2260 .map(|f| f / ((next_hops_aggregated_prop as u128).saturating_add(1_000_000)));
2261
2262 if let Some(hop_contribution) = hop_max_final_value_contribution {
2263 let hop_contribution: u64 = hop_contribution.try_into().unwrap_or(u64::MAX);
2264 if hop_contribution <= max_path_contribution.1 {
2265 max_path_contribution = (idx, hop_contribution);
2266 }
2267 } else { debug_assert!(false); }
2268 }
2269
2270 max_path_contribution
2271 }
2272}
2273
2274#[inline(always)]
2275#[rustfmt::skip]
2277fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option<u64> {
2278 amount_msat.checked_mul(channel_fees.proportional_millionths as u64)
2279 .and_then(|part| (channel_fees.base_msat as u64).checked_add(part / 1_000_000))
2280}
2281
2282#[inline(always)]
2283#[rustfmt::skip]
2286fn compute_fees_saturating(amount_msat: u64, channel_fees: RoutingFees) -> u64 {
2287 amount_msat.checked_mul(channel_fees.proportional_millionths as u64)
2288 .map(|prop| prop / 1_000_000).unwrap_or(u64::max_value())
2289 .saturating_add(channel_fees.base_msat as u64)
2290}
2291
2292fn default_node_features() -> NodeFeatures {
2298 let mut features = NodeFeatures::empty();
2299 features.set_variable_length_onion_optional();
2300 features
2301}
2302
2303struct LoggedPayeePubkey(Option<PublicKey>);
2304impl fmt::Display for LoggedPayeePubkey {
2305 #[rustfmt::skip]
2306 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2307 match self.0 {
2308 Some(pk) => {
2309 "payee node id ".fmt(f)?;
2310 pk.fmt(f)
2311 },
2312 None => {
2313 "blinded payee".fmt(f)
2314 },
2315 }
2316 }
2317}
2318
2319struct LoggedCandidateHop<'a>(&'a CandidateRouteHop<'a>);
2320impl<'a> fmt::Display for LoggedCandidateHop<'a> {
2321 #[rustfmt::skip]
2322 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2323 match self.0 {
2324 CandidateRouteHop::Blinded(BlindedPathCandidate { hint, .. }) | CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { hint, .. }) => {
2325 "blinded route hint with introduction node ".fmt(f)?;
2326 match hint.introduction_node() {
2327 IntroductionNode::NodeId(pubkey) => write!(f, "id {}", pubkey)?,
2328 IntroductionNode::DirectedShortChannelId(direction, scid) => {
2329 match direction {
2330 Direction::NodeOne => {
2331 write!(f, "one on channel with SCID {}", scid)?;
2332 },
2333 Direction::NodeTwo => {
2334 write!(f, "two on channel with SCID {}", scid)?;
2335 },
2336 }
2337 }
2338 }
2339 " and blinding point ".fmt(f)?;
2340 hint.blinding_point().fmt(f)
2341 },
2342 CandidateRouteHop::FirstHop(_) => {
2343 "first hop with SCID ".fmt(f)?;
2344 self.0.short_channel_id().unwrap().fmt(f)
2345 },
2346 CandidateRouteHop::PrivateHop(_) => {
2347 "route hint with SCID ".fmt(f)?;
2348 self.0.short_channel_id().unwrap().fmt(f)
2349 },
2350 _ => {
2351 "SCID ".fmt(f)?;
2352 self.0.short_channel_id().unwrap().fmt(f)
2353 },
2354 }
2355 }
2356}
2357
2358#[inline]
2359#[rustfmt::skip]
2360fn sort_first_hop_channels(
2361 channels: &mut Vec<&ChannelDetails>, used_liquidities: &HashMap<CandidateHopId, u64>,
2362 recommended_value_msat: u64, our_node_pubkey: &PublicKey
2363) {
2364 channels.sort_unstable_by(|chan_a, chan_b| {
2378 let chan_a_outbound_limit_msat = chan_a.next_outbound_htlc_limit_msat
2379 .saturating_sub(*used_liquidities.get(&CandidateHopId::Clear((chan_a.get_outbound_payment_scid().unwrap(),
2380 our_node_pubkey < &chan_a.counterparty.node_id))).unwrap_or(&0));
2381 let chan_b_outbound_limit_msat = chan_b.next_outbound_htlc_limit_msat
2382 .saturating_sub(*used_liquidities.get(&CandidateHopId::Clear((chan_b.get_outbound_payment_scid().unwrap(),
2383 our_node_pubkey < &chan_b.counterparty.node_id))).unwrap_or(&0));
2384 if chan_b_outbound_limit_msat < recommended_value_msat || chan_a_outbound_limit_msat < recommended_value_msat {
2385 chan_b_outbound_limit_msat.cmp(&chan_a_outbound_limit_msat)
2387 } else {
2388 chan_a_outbound_limit_msat.cmp(&chan_b_outbound_limit_msat)
2390 }
2391 });
2392}
2393
2394#[rustfmt::skip]
2420pub fn find_route<L: Deref, GL: Deref, S: ScoreLookUp>(
2421 our_node_pubkey: &PublicKey, route_params: &RouteParameters,
2422 network_graph: &NetworkGraph<GL>, first_hops: Option<&[&ChannelDetails]>, logger: L,
2423 scorer: &S, score_params: &S::ScoreParams, random_seed_bytes: &[u8; 32]
2424) -> Result<Route, &'static str>
2425where L::Target: Logger, GL::Target: Logger {
2426 let graph_lock = network_graph.read_only();
2427 let mut route = get_route(our_node_pubkey, &route_params, &graph_lock, first_hops, logger,
2428 scorer, score_params, random_seed_bytes)?;
2429 add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes);
2430 Ok(route)
2431}
2432
2433#[rustfmt::skip]
2434pub(crate) fn get_route<L: Deref, S: ScoreLookUp>(
2435 our_node_pubkey: &PublicKey, route_params: &RouteParameters, network_graph: &ReadOnlyNetworkGraph,
2436 first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S, score_params: &S::ScoreParams,
2437 _random_seed_bytes: &[u8; 32]
2438) -> Result<Route, &'static str>
2439where L::Target: Logger {
2440
2441 let payment_params = &route_params.payment_params;
2442 let max_path_length = core::cmp::min(payment_params.max_path_length, MAX_PATH_LENGTH_ESTIMATE);
2443 let final_value_msat = route_params.final_value_msat;
2444 let payee_node_id_opt = payment_params.payee.node_id().map(|pk| NodeId::from_pubkey(&pk));
2448 const DUMMY_BLINDED_PAYEE_ID: [u8; 33] = [2; 33];
2449 let maybe_dummy_payee_pk = payment_params.payee.node_id().unwrap_or_else(|| PublicKey::from_slice(&DUMMY_BLINDED_PAYEE_ID).unwrap());
2450 let maybe_dummy_payee_node_id = NodeId::from_pubkey(&maybe_dummy_payee_pk);
2451 let our_node_id = NodeId::from_pubkey(&our_node_pubkey);
2452
2453 if payee_node_id_opt.map_or(false, |payee| payee == our_node_id) {
2454 return Err("Cannot generate a route to ourselves");
2455 }
2456 if our_node_id == maybe_dummy_payee_node_id {
2457 return Err("Invalid origin node id provided, use a different one");
2458 }
2459
2460 if final_value_msat > MAX_VALUE_MSAT {
2461 return Err("Cannot generate a route of more value than all existing satoshis");
2462 }
2463
2464 if final_value_msat == 0 {
2465 return Err("Cannot send a payment of 0 msat");
2466 }
2467
2468 let final_cltv_expiry_delta = payment_params.payee.final_cltv_expiry_delta().unwrap_or(0);
2469 if payment_params.max_total_cltv_expiry_delta <= final_cltv_expiry_delta {
2470 return Err("Can't find a route where the maximum total CLTV expiry delta is below the final CLTV expiry.");
2471 }
2472
2473 let network_channels = network_graph.channels();
2530 let network_nodes = network_graph.nodes();
2531
2532 if payment_params.max_path_count == 0 {
2533 return Err("Can't find a route with no paths allowed.");
2534 }
2535
2536 let allow_mpp = if payment_params.max_path_count == 1 {
2540 false
2541 } else if payment_params.payee.supports_basic_mpp() {
2542 true
2543 } else if let Some(payee) = payee_node_id_opt {
2544 network_nodes.get(&payee).map_or(false, |node| node.announcement_info.as_ref().map_or(false,
2545 |info| info.features().supports_basic_mpp()))
2546 } else { false };
2547
2548 let max_total_routing_fee_msat = route_params.max_total_routing_fee_msat.unwrap_or(u64::max_value());
2549
2550 let first_hop_count = first_hops.map(|hops| hops.len()).unwrap_or(0);
2551 log_trace!(logger, "Searching for a route from payer {} to {} {} MPP and {} first hops {}overriding the network graph of {} nodes and {} channels with a fee limit of {} msat",
2552 our_node_pubkey, LoggedPayeePubkey(payment_params.payee.node_id()),
2553 if allow_mpp { "with" } else { "without" },
2554 first_hop_count, if first_hops.is_some() { "" } else { "not " },
2555 network_graph.nodes().len(), network_graph.channels().len(),
2556 max_total_routing_fee_msat);
2557
2558 if first_hop_count < 10 {
2559 if let Some(hops) = first_hops {
2560 for hop in hops {
2561 log_trace!(
2562 logger,
2563 " First hop through {}/{} can send between {}msat and {}msat (inclusive).",
2564 hop.counterparty.node_id,
2565 hop.get_outbound_payment_scid().unwrap_or(0),
2566 hop.next_outbound_htlc_minimum_msat,
2567 hop.next_outbound_htlc_limit_msat
2568 );
2569 }
2570 }
2571 }
2572
2573 let mut node_counter_builder = NodeCountersBuilder::new(&network_graph);
2574
2575 let payer_node_counter = node_counter_builder.select_node_counter_for_pubkey(*our_node_pubkey);
2576 let payee_node_counter = node_counter_builder.select_node_counter_for_pubkey(maybe_dummy_payee_pk);
2577
2578 for route in payment_params.payee.unblinded_route_hints().iter() {
2579 for hop in route.0.iter() {
2580 node_counter_builder.select_node_counter_for_pubkey(hop.src_node_id);
2581 }
2582 }
2583
2584 let mut first_hop_targets: HashMap<_, (Vec<&ChannelDetails>, u32)> =
2591 hash_map_with_capacity(if first_hops.is_some() { first_hops.as_ref().unwrap().len() } else { 0 });
2592 if let Some(hops) = first_hops {
2593 for chan in hops {
2594 if chan.get_outbound_payment_scid().is_none() {
2595 panic!("first_hops should be filled in with usable channels, not pending ones");
2596 }
2597 if chan.counterparty.node_id == *our_node_pubkey {
2598 return Err("First hop cannot have our_node_pubkey as a destination.");
2599 }
2600 let counterparty_id = NodeId::from_pubkey(&chan.counterparty.node_id);
2601 first_hop_targets
2602 .entry(counterparty_id)
2603 .or_insert_with(|| {
2604 let node_counter = node_counter_builder.select_node_counter_for_id(counterparty_id);
2606 (Vec::new(), node_counter)
2607 })
2608 .0.push(chan);
2609 }
2610 if first_hop_targets.is_empty() {
2611 return Err("Cannot route when there are no outbound routes away from us");
2612 }
2613 }
2614
2615 let node_counters = node_counter_builder.build();
2616
2617 let introduction_node_id_cache = calculate_blinded_path_intro_points(
2618 &payment_params, &node_counters, network_graph, &logger, our_node_id, &first_hop_targets,
2619 )?;
2620
2621 let mut last_hop_candidates =
2622 hash_map_with_capacity(payment_params.payee.unblinded_route_hints().len());
2623 for route in payment_params.payee.unblinded_route_hints().iter()
2624 .filter(|route| !route.0.is_empty())
2625 {
2626 let hop_iter = route.0.iter().rev();
2627 let prev_hop_iter = core::iter::once(&maybe_dummy_payee_pk).chain(
2628 route.0.iter().skip(1).rev().map(|hop| &hop.src_node_id));
2629
2630 for (hop, prev_hop_id) in hop_iter.zip(prev_hop_iter) {
2631 let (target, private_target_node_counter) =
2632 node_counters.private_node_counter_from_pubkey(&prev_hop_id)
2633 .ok_or_else(|| {
2634 debug_assert!(false);
2635 "We should always have private target node counters available"
2636 })?;
2637 let (_src_id, private_source_node_counter) =
2638 node_counters.private_node_counter_from_pubkey(&hop.src_node_id)
2639 .ok_or_else(|| {
2640 debug_assert!(false);
2641 "We should always have private source node counters available"
2642 })?;
2643
2644 if let Some((first_channels, _)) = first_hop_targets.get(target) {
2645 let matches_an_scid = |d: &&ChannelDetails|
2646 d.outbound_scid_alias == Some(hop.short_channel_id) || d.short_channel_id == Some(hop.short_channel_id);
2647 if first_channels.iter().any(matches_an_scid) {
2648 log_trace!(logger, "Ignoring route hint with SCID {} (and any previous) due to it being a direct channel of ours.",
2649 hop.short_channel_id);
2650 break;
2651 }
2652 }
2653
2654 let candidate = network_channels
2655 .get(&hop.short_channel_id)
2656 .and_then(|channel| channel.as_directed_to(target))
2657 .map(|(info, _)| CandidateRouteHop::PublicHop(PublicHopCandidate {
2658 info,
2659 short_channel_id: hop.short_channel_id,
2660 }))
2661 .unwrap_or_else(|| CandidateRouteHop::PrivateHop(PrivateHopCandidate {
2662 hint: hop, target_node_id: target,
2663 source_node_counter: *private_source_node_counter,
2664 target_node_counter: *private_target_node_counter,
2665 }));
2666
2667 last_hop_candidates.entry(private_target_node_counter).or_insert_with(Vec::new).push(candidate);
2668 }
2669 }
2670
2671 let mut targets: BinaryHeap<RouteGraphNode> = BinaryHeap::new();
2675
2676 let dist_len = node_counters.max_counter() + 1;
2679 let mut dist: Vec<Option<PathBuildingHop>> = vec![None; dist_len as usize];
2680
2681 let mut hit_minimum_limit;
2685
2686 const ROUTE_CAPACITY_PROVISION_FACTOR: u64 = 3;
2691 let recommended_value_msat = final_value_msat * ROUTE_CAPACITY_PROVISION_FACTOR as u64;
2692 let mut path_value_msat = final_value_msat;
2693
2694 let minimal_value_contribution_msat: u64 = if allow_mpp {
2704 (final_value_msat + (payment_params.max_path_count as u64 - 1)) / payment_params.max_path_count as u64
2705 } else {
2706 final_value_msat
2707 };
2708
2709 let mut channel_saturation_pow_half = payment_params.max_channel_saturation_power_of_half;
2713
2714 let max_total_cltv_expiry_delta: u16 =
2718 (payment_params.max_total_cltv_expiry_delta - final_cltv_expiry_delta)
2719 .checked_sub(2*MEDIAN_HOP_CLTV_EXPIRY_DELTA)
2720 .unwrap_or(payment_params.max_total_cltv_expiry_delta - final_cltv_expiry_delta)
2721 .try_into()
2722 .unwrap_or(u16::MAX);
2723
2724 let mut used_liquidities: HashMap<CandidateHopId, u64> =
2730 hash_map_with_capacity(network_nodes.len());
2731
2732 let mut already_collected_value_msat = 0;
2735
2736 for (_, (channels, _)) in first_hop_targets.iter_mut() {
2737 sort_first_hop_channels(channels, &used_liquidities, recommended_value_msat,
2738 our_node_pubkey);
2739 }
2740
2741 log_trace!(logger, "Building path from {} to payer {} for value {} msat.",
2742 LoggedPayeePubkey(payment_params.payee.node_id()), our_node_pubkey, final_value_msat);
2743
2744 let mut num_ignored_value_contribution: u32 = 0;
2746 let mut num_ignored_path_length_limit: u32 = 0;
2747 let mut num_ignored_cltv_delta_limit: u32 = 0;
2748 let mut num_ignored_previously_failed: u32 = 0;
2749 let mut num_ignored_total_fee_limit: u32 = 0;
2750 let mut num_ignored_avoid_overpayment: u32 = 0;
2751 let mut num_ignored_htlc_minimum_msat_limit: u32 = 0;
2752
2753 macro_rules! add_entry {
2754 ( $candidate: expr, $next_hops_fee_msat: expr,
2759 $next_hops_value_contribution: expr, $next_hops_path_htlc_minimum_msat: expr,
2760 $next_hops_path_penalty_msat: expr, $next_hops_cltv_delta: expr, $next_hops_path_length: expr ) => { {
2761 let mut hop_contribution_amt_msat = None;
2764
2765 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
2766 if let Some(counter) = $candidate.target_node_counter() {
2767 if let Some(node) = &mut dist[counter as usize] {
2771 node.best_path_from_hop_selected = true;
2772 } else if counter != payee_node_counter {
2773 panic!("No dist entry for target node counter {}", counter);
2774 }
2775 }
2776
2777 let src_node_id = $candidate.source();
2782 if Some(src_node_id) != $candidate.target() {
2783 let scid_opt = $candidate.short_channel_id();
2784 let effective_capacity = $candidate.effective_capacity();
2785 let htlc_maximum_msat = max_htlc_from_capacity(effective_capacity, channel_saturation_pow_half);
2786
2787 if let Some(mut available_value_contribution_msat) = htlc_maximum_msat.checked_sub($next_hops_fee_msat) {
2795 let cltv_expiry_delta = $candidate.cltv_expiry_delta();
2796 let htlc_minimum_msat = $candidate.htlc_minimum_msat();
2797 let used_liquidity_msat = used_liquidities
2798 .get(&$candidate.id())
2799 .map_or(0, |used_liquidity_msat| {
2800 available_value_contribution_msat = available_value_contribution_msat
2801 .saturating_sub(*used_liquidity_msat);
2802 *used_liquidity_msat
2803 });
2804
2805 let path_length_to_node = $next_hops_path_length
2807 + if $candidate.blinded_hint_idx().is_some() { 0 } else { 1 };
2808 let exceeds_max_path_length = path_length_to_node > max_path_length;
2809
2810 let hop_total_cltv_delta = ($next_hops_cltv_delta as u32)
2812 .saturating_add(cltv_expiry_delta);
2813 let exceeds_cltv_delta_limit = hop_total_cltv_delta > max_total_cltv_expiry_delta as u32;
2814
2815 let value_contribution_msat = cmp::min(available_value_contribution_msat, $next_hops_value_contribution);
2816 let contributes_sufficient_value = value_contribution_msat >= minimal_value_contribution_msat;
2818 let amount_to_transfer_over_msat: u64 = match value_contribution_msat.checked_add($next_hops_fee_msat) {
2820 Some(result) => result,
2821 None => unreachable!(),
2823 };
2824 #[allow(unused_comparisons)] let over_path_minimum_msat = amount_to_transfer_over_msat >= htlc_minimum_msat &&
2826 amount_to_transfer_over_msat >= $next_hops_path_htlc_minimum_msat;
2827
2828 #[allow(unused_comparisons)] let may_overpay_to_meet_path_minimum_msat =
2830 (amount_to_transfer_over_msat < htlc_minimum_msat &&
2831 recommended_value_msat >= htlc_minimum_msat) ||
2832 (amount_to_transfer_over_msat < $next_hops_path_htlc_minimum_msat &&
2833 recommended_value_msat >= $next_hops_path_htlc_minimum_msat);
2834
2835 let payment_failed_on_this_channel = match scid_opt {
2836 Some(scid) => payment_params.previously_failed_channels.contains(&scid),
2837 None => match $candidate.blinded_hint_idx() {
2838 Some(idx) => {
2839 payment_params.previously_failed_blinded_path_idxs.contains(&(idx as u64))
2840 },
2841 None => false,
2842 },
2843 };
2844
2845 let (should_log_candidate, first_hop_details) = match $candidate {
2846 CandidateRouteHop::FirstHop(hop) => (true, Some(hop.details)),
2847 CandidateRouteHop::PrivateHop(_) => (true, None),
2848 CandidateRouteHop::Blinded(_) => (true, None),
2849 CandidateRouteHop::OneHopBlinded(_) => (true, None),
2850 _ => (false, None),
2851 };
2852
2853 if !contributes_sufficient_value {
2858 if should_log_candidate {
2859 log_trace!(logger, "Ignoring {} due to insufficient value contribution (channel max {:?}).",
2860 LoggedCandidateHop(&$candidate),
2861 effective_capacity);
2862 }
2863 num_ignored_value_contribution += 1;
2864 } else if exceeds_max_path_length {
2865 if should_log_candidate {
2866 log_trace!(logger, "Ignoring {} due to exceeding maximum path length limit.", LoggedCandidateHop(&$candidate));
2867 }
2868 num_ignored_path_length_limit += 1;
2869 } else if exceeds_cltv_delta_limit {
2870 if should_log_candidate {
2871 log_trace!(logger, "Ignoring {} due to exceeding CLTV delta limit.", LoggedCandidateHop(&$candidate));
2872
2873 if let Some(_) = first_hop_details {
2874 log_trace!(logger,
2875 "First hop candidate cltv_expiry_delta: {}. Limit: {}",
2876 hop_total_cltv_delta,
2877 max_total_cltv_expiry_delta,
2878 );
2879 }
2880 }
2881 num_ignored_cltv_delta_limit += 1;
2882 } else if payment_failed_on_this_channel {
2883 if should_log_candidate {
2884 log_trace!(logger, "Ignoring {} due to a failed previous payment attempt.", LoggedCandidateHop(&$candidate));
2885 }
2886 num_ignored_previously_failed += 1;
2887 } else if may_overpay_to_meet_path_minimum_msat {
2888 if should_log_candidate {
2889 log_trace!(logger,
2890 "Ignoring {} to avoid overpaying to meet htlc_minimum_msat limit ({}).",
2891 LoggedCandidateHop(&$candidate), $candidate.htlc_minimum_msat());
2892 }
2893 num_ignored_avoid_overpayment += 1;
2894 hit_minimum_limit = true;
2895 } else if over_path_minimum_msat {
2896 let curr_min = cmp::max(
2901 $next_hops_path_htlc_minimum_msat, htlc_minimum_msat
2902 );
2903 let src_node_counter = $candidate.src_node_counter();
2904 let mut candidate_fees = $candidate.fees();
2905 if src_node_counter == payer_node_counter {
2906 candidate_fees = RoutingFees {
2908 proportional_millionths: 0,
2909 base_msat: 0,
2910 };
2911 }
2912 let path_htlc_minimum_msat = compute_fees_saturating(curr_min, candidate_fees)
2913 .saturating_add(curr_min);
2914
2915 let dist_entry = &mut dist[src_node_counter as usize];
2916 let old_entry = if let Some(hop) = dist_entry {
2917 hop
2918 } else {
2919 *dist_entry = Some(PathBuildingHop {
2925 candidate: $candidate.clone(),
2926 fee_msat: 0,
2927 next_hops_fee_msat: u64::max_value(),
2928 hop_use_fee_msat: u64::max_value(),
2929 total_fee_msat: u64::max_value(),
2930 path_htlc_minimum_msat,
2931 path_penalty_msat: u64::max_value(),
2932 was_processed: false,
2933 is_first_hop_target: false,
2934 is_last_hop_target: false,
2935 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
2936 best_path_from_hop_selected: false,
2937 value_contribution_msat,
2938 });
2939 dist_entry.as_mut().unwrap()
2940 };
2941
2942 #[allow(unused_mut)] let mut should_process = !old_entry.was_processed;
2944 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
2945 {
2946 if !should_process { should_process = true; }
2949 }
2950
2951 if should_process {
2952 let mut hop_use_fee_msat = 0;
2953 let mut total_fee_msat: u64 = $next_hops_fee_msat;
2954
2955 if src_node_id != our_node_id {
2958 hop_use_fee_msat = compute_fees_saturating(amount_to_transfer_over_msat, candidate_fees);
2961 total_fee_msat = total_fee_msat.saturating_add(hop_use_fee_msat);
2962 }
2963
2964 if total_fee_msat > max_total_routing_fee_msat {
2966 if should_log_candidate {
2967 log_trace!(logger, "Ignoring {} with fee {total_fee_msat} due to exceeding max total routing fee limit {max_total_routing_fee_msat}.", LoggedCandidateHop(&$candidate));
2968
2969 if let Some(_) = first_hop_details {
2970 log_trace!(logger,
2971 "First hop candidate routing fee: {}. Limit: {}",
2972 total_fee_msat,
2973 max_total_routing_fee_msat,
2974 );
2975 }
2976 }
2977 num_ignored_total_fee_limit += 1;
2978 } else {
2979 let channel_usage = ChannelUsage {
2980 amount_msat: amount_to_transfer_over_msat,
2981 inflight_htlc_msat: used_liquidity_msat,
2982 effective_capacity,
2983 };
2984 let channel_penalty_msat =
2985 scorer.channel_penalty_msat($candidate,
2986 channel_usage,
2987 score_params);
2988 let path_penalty_msat = $next_hops_path_penalty_msat
2989 .saturating_add(channel_penalty_msat);
2990
2991 let old_fee_cost = cmp::max(old_entry.total_fee_msat, old_entry.path_htlc_minimum_msat)
3009 .saturating_add(old_entry.path_penalty_msat);
3010 let new_fee_cost = cmp::max(total_fee_msat, path_htlc_minimum_msat)
3011 .saturating_add(path_penalty_msat);
3012 let old_cost = if old_fee_cost != u64::MAX && old_entry.value_contribution_msat != 0 {
3020 ((old_fee_cost as u128) << 64) / old_entry.value_contribution_msat as u128
3021 } else {
3022 u128::MAX
3023 };
3024 let new_cost = if new_fee_cost != u64::MAX {
3025 ((new_fee_cost as u128) << 64) / value_contribution_msat as u128
3028 } else {
3029 u128::MAX
3030 };
3031
3032 if !old_entry.was_processed && new_cost < old_cost {
3033 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
3034 {
3035 assert!(!old_entry.best_path_from_hop_selected);
3036 assert!(hop_total_cltv_delta <= u16::MAX as u32);
3037 }
3038
3039 let new_graph_node = RouteGraphNode {
3040 node_counter: src_node_counter,
3041 score: new_cost,
3042 total_cltv_delta: hop_total_cltv_delta as u16,
3043 value_contribution_msat,
3044 path_length_to_node,
3045 };
3046 targets.push(new_graph_node);
3047 old_entry.next_hops_fee_msat = $next_hops_fee_msat;
3048 old_entry.hop_use_fee_msat = hop_use_fee_msat;
3049 old_entry.total_fee_msat = total_fee_msat;
3050 old_entry.candidate = $candidate.clone();
3051 old_entry.fee_msat = 0; old_entry.path_htlc_minimum_msat = path_htlc_minimum_msat;
3053 old_entry.path_penalty_msat = path_penalty_msat;
3054 old_entry.value_contribution_msat = value_contribution_msat;
3055 hop_contribution_amt_msat = Some(value_contribution_msat);
3056 } else if old_entry.was_processed && new_cost < old_cost {
3057 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
3058 {
3059 debug_assert!(path_htlc_minimum_msat < old_entry.path_htlc_minimum_msat);
3079 debug_assert!(
3080 value_contribution_msat + path_penalty_msat <
3081 old_entry.value_contribution_msat + old_entry.path_penalty_msat
3082 );
3083 }
3084 }
3085 }
3086 }
3087 } else {
3088 if should_log_candidate {
3089 log_trace!(logger,
3090 "Ignoring {} due to its htlc_minimum_msat limit.",
3091 LoggedCandidateHop(&$candidate));
3092
3093 if let Some(details) = first_hop_details {
3094 log_trace!(logger,
3095 "First hop candidate next_outbound_htlc_minimum_msat: {}",
3096 details.next_outbound_htlc_minimum_msat,
3097 );
3098 }
3099 }
3100 num_ignored_htlc_minimum_msat_limit += 1;
3101 }
3102 }
3103 }
3104 hop_contribution_amt_msat
3105 } }
3106 }
3107
3108 let default_node_features = default_node_features();
3109
3110 #[rustfmt::skip]
3116 macro_rules! add_entries_to_cheapest_to_target_node {
3117 ( $node_counter: expr, $node_id: expr, $next_hops_value_contribution: expr,
3118 $next_hops_cltv_delta: expr, $next_hops_path_length: expr ) => {
3119 let fee_to_target_msat;
3120 let next_hops_path_htlc_minimum_msat;
3121 let next_hops_path_penalty_msat;
3122 let (is_first_hop_target, is_last_hop_target);
3123 let skip_node = if let Some(elem) = &mut dist[$node_counter as usize] {
3124 let was_processed = elem.was_processed;
3125 elem.was_processed = true;
3126 fee_to_target_msat = elem.total_fee_msat;
3127 next_hops_path_htlc_minimum_msat = elem.path_htlc_minimum_msat;
3128 next_hops_path_penalty_msat = elem.path_penalty_msat;
3129 is_first_hop_target = elem.is_first_hop_target;
3130 is_last_hop_target = elem.is_last_hop_target;
3131 was_processed
3132 } else {
3133 debug_assert_eq!($node_id, maybe_dummy_payee_node_id);
3137
3138 fee_to_target_msat = 0;
3139 next_hops_path_htlc_minimum_msat = 0;
3140 next_hops_path_penalty_msat = 0;
3141 is_first_hop_target = false;
3142 is_last_hop_target = false;
3143 false
3144 };
3145
3146 if !skip_node {
3147 if is_last_hop_target {
3148 if let Some(candidates) = last_hop_candidates.get(&$node_counter) {
3149 for candidate in candidates {
3150 add_entry!(candidate, fee_to_target_msat,
3151 $next_hops_value_contribution,
3152 next_hops_path_htlc_minimum_msat, next_hops_path_penalty_msat,
3153 $next_hops_cltv_delta, $next_hops_path_length);
3154 }
3155 }
3156 }
3157 if is_first_hop_target {
3158 if let Some((first_channels, peer_node_counter)) = first_hop_targets.get(&$node_id) {
3159 for details in first_channels {
3160 debug_assert_eq!(*peer_node_counter, $node_counter);
3161 let candidate = CandidateRouteHop::FirstHop(FirstHopCandidate {
3162 details, payer_node_id: &our_node_id, payer_node_counter,
3163 target_node_counter: $node_counter,
3164 });
3165 add_entry!(&candidate, fee_to_target_msat,
3166 $next_hops_value_contribution,
3167 next_hops_path_htlc_minimum_msat, next_hops_path_penalty_msat,
3168 $next_hops_cltv_delta, $next_hops_path_length);
3169 }
3170 }
3171 }
3172
3173 if let Some(node) = network_nodes.get(&$node_id) {
3174 let features = if let Some(node_info) = node.announcement_info.as_ref() {
3175 &node_info.features()
3176 } else {
3177 &default_node_features
3178 };
3179
3180 if !features.requires_unknown_bits() {
3181 for chan_id in node.channels.iter() {
3182 let chan = network_channels.get(chan_id).unwrap();
3183 if !chan.features.requires_unknown_bits() {
3184 if let Some((directed_channel, source)) = chan.as_directed_to(&$node_id) {
3185 if first_hops.is_none() || *source != our_node_id {
3186 if directed_channel.direction().enabled {
3187 let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate {
3188 info: directed_channel,
3189 short_channel_id: *chan_id,
3190 });
3191 add_entry!(&candidate,
3192 fee_to_target_msat,
3193 $next_hops_value_contribution,
3194 next_hops_path_htlc_minimum_msat,
3195 next_hops_path_penalty_msat,
3196 $next_hops_cltv_delta, $next_hops_path_length);
3197 }
3198 }
3199 }
3200 }
3201 }
3202 }
3203 }
3204 }
3205 };
3206 }
3207
3208 let mut payment_paths = Vec::<PaymentPath>::new();
3209
3210 'paths_collection: loop {
3212 targets.clear();
3215 for e in dist.iter_mut() {
3216 *e = None;
3217 }
3218
3219 for (_, (chans, peer_node_counter)) in first_hop_targets.iter() {
3229 dist[*peer_node_counter as usize] = Some(PathBuildingHop {
3236 candidate: CandidateRouteHop::FirstHop(FirstHopCandidate {
3237 details: &chans[0],
3238 payer_node_id: &our_node_id,
3239 target_node_counter: u32::max_value(),
3240 payer_node_counter: u32::max_value(),
3241 }),
3242 fee_msat: 0,
3243 next_hops_fee_msat: u64::max_value(),
3244 hop_use_fee_msat: u64::max_value(),
3245 total_fee_msat: u64::max_value(),
3246 path_htlc_minimum_msat: u64::max_value(),
3247 path_penalty_msat: u64::max_value(),
3248 was_processed: false,
3249 is_first_hop_target: true,
3250 is_last_hop_target: false,
3251 value_contribution_msat: 0,
3252 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
3253 best_path_from_hop_selected: false,
3254 });
3255 }
3256 for (target_node_counter, candidates) in last_hop_candidates.iter() {
3257 debug_assert!(!candidates.is_empty());
3264 if candidates.is_empty() { continue }
3265 let entry = &mut dist[**target_node_counter as usize];
3266 if let Some(hop) = entry {
3267 hop.is_last_hop_target = true;
3268 } else {
3269 *entry = Some(PathBuildingHop {
3270 candidate: candidates[0].clone(),
3271 fee_msat: 0,
3272 next_hops_fee_msat: u64::max_value(),
3273 hop_use_fee_msat: u64::max_value(),
3274 total_fee_msat: u64::max_value(),
3275 path_htlc_minimum_msat: u64::max_value(),
3276 path_penalty_msat: u64::max_value(),
3277 was_processed: false,
3278 is_first_hop_target: false,
3279 is_last_hop_target: true,
3280 value_contribution_msat: 0,
3281 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
3282 best_path_from_hop_selected: false,
3283 });
3284 }
3285 }
3286 hit_minimum_limit = false;
3287
3288 if let Some(payee) = payee_node_id_opt {
3289 if let Some(entry) = &mut dist[payee_node_counter as usize] {
3290 entry.next_hops_fee_msat = 0;
3293 entry.hop_use_fee_msat = 0;
3294 entry.total_fee_msat = 0;
3295 entry.path_htlc_minimum_msat = 0;
3296 entry.path_penalty_msat = 0;
3297 entry.value_contribution_msat = path_value_msat;
3298 }
3299 add_entries_to_cheapest_to_target_node!(
3300 payee_node_counter, payee, path_value_msat, 0, 0
3301 );
3302 }
3303
3304 debug_assert_eq!(
3305 payment_params.payee.blinded_route_hints().len(),
3306 introduction_node_id_cache.len(),
3307 "introduction_node_id_cache was built by iterating the blinded_route_hints, so they should be the same len"
3308 );
3309 let mut blind_intros_added = hash_map_with_capacity(payment_params.payee.blinded_route_hints().len());
3310 for (hint_idx, hint) in payment_params.payee.blinded_route_hints().iter().enumerate() {
3311 let source_node_opt = introduction_node_id_cache[hint_idx];
3315 let (source_node_id, source_node_counter) = if let Some(v) = source_node_opt { v } else { continue };
3316 if our_node_id == *source_node_id { continue }
3317 let candidate = if hint.blinded_hops().len() == 1 {
3318 CandidateRouteHop::OneHopBlinded(
3319 OneHopBlindedPathCandidate { source_node_counter, source_node_id, hint, hint_idx }
3320 )
3321 } else {
3322 CandidateRouteHop::Blinded(BlindedPathCandidate { source_node_counter, source_node_id, hint, hint_idx })
3323 };
3324 if let Some(hop_used_msat) = add_entry!(&candidate,
3325 0, path_value_msat, 0, 0_u64, 0, 0)
3326 {
3327 blind_intros_added.insert(source_node_id, (hop_used_msat, candidate));
3328 } else { continue }
3329 }
3330 for (source_node_id, (path_contribution_msat, candidate)) in blind_intros_added {
3339 if let Some((first_channels, peer_node_counter)) = first_hop_targets.get_mut(source_node_id) {
3340 sort_first_hop_channels(
3341 first_channels, &used_liquidities, recommended_value_msat, our_node_pubkey
3342 );
3343 for details in first_channels {
3344 let first_hop_candidate = CandidateRouteHop::FirstHop(FirstHopCandidate {
3345 details, payer_node_id: &our_node_id, payer_node_counter,
3346 target_node_counter: *peer_node_counter,
3347 });
3348 let blinded_path_fee = match compute_fees(path_contribution_msat, candidate.fees()) {
3349 Some(fee) => fee,
3350 None => continue
3351 };
3352 let path_min = candidate.htlc_minimum_msat().saturating_add(
3353 compute_fees_saturating(candidate.htlc_minimum_msat(), candidate.fees()));
3354 add_entry!(&first_hop_candidate, blinded_path_fee, path_contribution_msat, path_min,
3355 0_u64, candidate.cltv_expiry_delta(), 0);
3356 }
3357 }
3358 }
3359
3360 log_trace!(logger, "Starting main path collection loop with {} nodes pre-filled from first/last hops.", targets.len());
3361
3362 let mut found_new_path = false;
3365
3366 'path_construction: while let Some(RouteGraphNode { node_counter, total_cltv_delta, mut value_contribution_msat, path_length_to_node, .. }) = targets.pop() {
3376
3377 if node_counter == payer_node_counter {
3380 let mut new_entry = dist[payer_node_counter as usize].take().unwrap();
3381 let mut ordered_hops: Vec<(PathBuildingHop, NodeFeatures)> = vec!((new_entry.clone(), default_node_features.clone()));
3382
3383 'path_walk: loop {
3384 let mut features_set = false;
3385 let candidate = &ordered_hops.last().unwrap().0.candidate;
3386 let target = candidate.target().unwrap_or(maybe_dummy_payee_node_id);
3387 let target_node_counter = candidate.target_node_counter();
3388 if let Some((first_channels, _)) = first_hop_targets.get(&target) {
3389 for details in first_channels {
3390 if let CandidateRouteHop::FirstHop(FirstHopCandidate { details: last_hop_details, .. })
3391 = candidate
3392 {
3393 if details.get_outbound_payment_scid() == last_hop_details.get_outbound_payment_scid() {
3394 ordered_hops.last_mut().unwrap().1 = details.counterparty.features.to_context();
3395 features_set = true;
3396 break;
3397 }
3398 }
3399 }
3400 }
3401 if !features_set {
3402 if let Some(node) = network_nodes.get(&target) {
3403 if let Some(node_info) = node.announcement_info.as_ref() {
3404 ordered_hops.last_mut().unwrap().1 = node_info.features().clone();
3405 } else {
3406 ordered_hops.last_mut().unwrap().1 = default_node_features.clone();
3407 }
3408 } else {
3409 }
3413 }
3414
3415 if target_node_counter.is_none() {
3420 break 'path_walk;
3421 }
3422 if target_node_counter == Some(payee_node_counter) { break 'path_walk; }
3423
3424 new_entry = match dist[target_node_counter.unwrap() as usize].take() {
3425 Some(payment_hop) => payment_hop,
3426 None => unreachable!(),
3429 };
3430 ordered_hops.last_mut().unwrap().0.fee_msat = new_entry.hop_use_fee_msat;
3434 ordered_hops.push((new_entry.clone(), default_node_features.clone()));
3435 }
3436 ordered_hops.last_mut().unwrap().0.fee_msat = value_contribution_msat;
3437 ordered_hops.last_mut().unwrap().0.hop_use_fee_msat = 0;
3438
3439 log_trace!(logger, "Found a path back to us from the target with {} hops contributing up to {} msat: \n {:#?}",
3440 ordered_hops.len(), value_contribution_msat, ordered_hops.iter().map(|h| &(h.0)).collect::<Vec<&PathBuildingHop>>());
3441
3442 let mut payment_path = PaymentPath {hops: ordered_hops};
3443
3444 debug_assert_eq!(payment_path.get_value_msat(), value_contribution_msat);
3450 let (lowest_value_contrib_hop, max_path_contribution_msat) =
3451 payment_path.max_final_value_msat(&used_liquidities, channel_saturation_pow_half);
3452 let desired_value_contribution = cmp::min(max_path_contribution_msat, final_value_msat);
3453 value_contribution_msat = payment_path.update_value_and_recompute_fees(desired_value_contribution);
3454
3455 for (hop, _) in payment_path.hops.iter() {
3465 let spent_on_hop_msat = value_contribution_msat + hop.next_hops_fee_msat;
3466 let used_liquidity_msat = used_liquidities
3467 .entry(hop.candidate.id())
3468 .and_modify(|used_liquidity_msat| *used_liquidity_msat += spent_on_hop_msat)
3469 .or_insert(spent_on_hop_msat);
3470 let hop_capacity = hop.candidate.effective_capacity();
3471 let hop_max_msat = max_htlc_from_capacity(hop_capacity, channel_saturation_pow_half);
3472 debug_assert!(*used_liquidity_msat <= hop_max_msat);
3473 }
3474 if max_path_contribution_msat > value_contribution_msat {
3475 let victim_candidate = &payment_path.hops[(payment_path.hops.len()) / 2].0.candidate;
3479 let exhausted = u64::max_value();
3480 log_trace!(logger,
3481 "Disabling route candidate {} for future path building iterations to avoid duplicates.",
3482 LoggedCandidateHop(victim_candidate));
3483 if let Some(scid) = victim_candidate.short_channel_id() {
3484 *used_liquidities.entry(CandidateHopId::Clear((scid, false))).or_default() = exhausted;
3485 *used_liquidities.entry(CandidateHopId::Clear((scid, true))).or_default() = exhausted;
3486 }
3487 } else {
3488 log_trace!(logger, "Path was limited to {}msat by hop {}", max_path_contribution_msat, lowest_value_contrib_hop);
3489 }
3490
3491 already_collected_value_msat += value_contribution_msat;
3494
3495 payment_paths.push(payment_path);
3496 found_new_path = true;
3497 break 'path_construction;
3498 }
3499
3500 if node_counter == payee_node_counter { continue 'path_construction; }
3504
3505 let node_id = if let Some(entry) = &dist[node_counter as usize] {
3506 entry.candidate.source()
3507 } else {
3508 debug_assert!(false, "Best nodes in the heap should have entries in dist");
3509 continue 'path_construction;
3510 };
3511
3512 add_entries_to_cheapest_to_target_node!(
3516 node_counter, node_id,
3517 value_contribution_msat,
3518 total_cltv_delta, path_length_to_node
3519 );
3520 }
3521
3522 if !allow_mpp {
3523 if !found_new_path && channel_saturation_pow_half != 0 {
3524 channel_saturation_pow_half = 0;
3525 continue 'paths_collection;
3526 }
3527 break 'paths_collection;
3529 }
3530
3531 if !found_new_path && channel_saturation_pow_half != 0 {
3537 channel_saturation_pow_half = 0;
3538 } else if !found_new_path && hit_minimum_limit && already_collected_value_msat < final_value_msat && path_value_msat != recommended_value_msat {
3539 log_trace!(logger, "Failed to collect enough value, but running again to collect extra paths with a potentially higher limit.");
3540 path_value_msat = recommended_value_msat;
3541 } else if already_collected_value_msat >= recommended_value_msat || !found_new_path {
3542 log_trace!(logger, "Have now collected {} msat (seeking {} msat) in paths. Last path loop {} a new path.",
3543 already_collected_value_msat, recommended_value_msat, if found_new_path { "found" } else { "did not find" });
3544 break 'paths_collection;
3545 } else if found_new_path && already_collected_value_msat == final_value_msat && payment_paths.len() == 1 {
3546 if !hit_minimum_limit {
3552 log_trace!(logger, "Collected exactly our payment amount on the first pass, without hitting an htlc_minimum_msat limit, exiting.");
3553 break 'paths_collection;
3554 }
3555 log_trace!(logger, "Collected our payment amount on the first pass, but running again to collect extra paths with a potentially higher value to meet htlc_minimum_msat limit.");
3556 path_value_msat = recommended_value_msat;
3557 }
3558 }
3559
3560 let num_ignored_total = num_ignored_value_contribution + num_ignored_path_length_limit +
3561 num_ignored_cltv_delta_limit + num_ignored_previously_failed +
3562 num_ignored_avoid_overpayment + num_ignored_htlc_minimum_msat_limit +
3563 num_ignored_total_fee_limit;
3564 if num_ignored_total > 0 {
3565 log_trace!(logger,
3566 "Ignored {} candidate hops due to insufficient value contribution, {} due to path length limit, {} due to CLTV delta limit, {} due to previous payment failure, {} due to htlc_minimum_msat limit, {} to avoid overpaying, {} due to maximum total fee limit. Total: {} ignored candidates.",
3567 num_ignored_value_contribution, num_ignored_path_length_limit,
3568 num_ignored_cltv_delta_limit, num_ignored_previously_failed,
3569 num_ignored_htlc_minimum_msat_limit, num_ignored_avoid_overpayment,
3570 num_ignored_total_fee_limit, num_ignored_total);
3571 }
3572
3573 if payment_paths.len() == 0 {
3575 return Err("Failed to find a path to the given destination");
3576 }
3577
3578 if already_collected_value_msat < final_value_msat {
3579 return Err("Failed to find a sufficient route to the given destination");
3580 }
3581
3582 let mut selected_route = payment_paths;
3584
3585 debug_assert_eq!(selected_route.iter().map(|p| p.get_value_msat()).sum::<u64>(), already_collected_value_msat);
3586 let mut overpaid_value_msat = already_collected_value_msat - final_value_msat;
3587
3588 selected_route.sort_unstable_by(|a, b| b.get_cost_per_msat().cmp(&a.get_cost_per_msat()));
3592
3593 let mut paths_left = selected_route.len();
3595 selected_route.retain(|path| {
3596 if paths_left == 1 {
3597 return true
3598 }
3599 let path_value_msat = path.get_value_msat();
3600 if path_value_msat <= overpaid_value_msat {
3601 overpaid_value_msat -= path_value_msat;
3602 paths_left -= 1;
3603 return false;
3604 }
3605 true
3606 });
3607 debug_assert!(selected_route.len() > 0);
3608
3609 if overpaid_value_msat != 0 {
3610 selected_route.sort_unstable_by(|a, b| {
3615 let a_f = a.hops.iter().map(|hop| hop.0.candidate.fees().proportional_millionths as u64).sum::<u64>();
3616 let b_f = b.hops.iter().map(|hop| hop.0.candidate.fees().proportional_millionths as u64).sum::<u64>();
3617 a_f.cmp(&b_f).then_with(|| b.get_cost_msat().cmp(&a.get_cost_msat()))
3618 });
3619 let expensive_payment_path = selected_route.first_mut().unwrap();
3620
3621 let expensive_path_new_value_msat = expensive_payment_path.get_value_msat() - overpaid_value_msat;
3624 expensive_payment_path.update_value_and_recompute_fees(expensive_path_new_value_msat);
3625 }
3626
3627 selected_route.sort_unstable_by_key(|path| {
3633 let mut key = [CandidateHopId::Clear((42, true)) ; MAX_PATH_LENGTH_ESTIMATE as usize];
3634 debug_assert!(path.hops.len() <= key.len());
3635 for (scid, key) in path.hops.iter() .map(|h| h.0.candidate.id()).zip(key.iter_mut()) {
3636 *key = scid;
3637 }
3638 key
3639 });
3640 for idx in 0..(selected_route.len() - 1) {
3641 if idx + 1 >= selected_route.len() { break; }
3642 if iter_equal(selected_route[idx ].hops.iter().map(|h| (h.0.candidate.id(), h.0.candidate.target())),
3643 selected_route[idx + 1].hops.iter().map(|h| (h.0.candidate.id(), h.0.candidate.target()))) {
3644 let new_value = selected_route[idx].get_value_msat() + selected_route[idx + 1].get_value_msat();
3645 selected_route[idx].update_value_and_recompute_fees(new_value);
3646 selected_route.remove(idx + 1);
3647 }
3648 }
3649
3650 let mut paths = Vec::new();
3651 for payment_path in selected_route {
3652 let mut hops = Vec::with_capacity(payment_path.hops.len());
3653 for (hop, node_features) in payment_path.hops.iter()
3654 .filter(|(h, _)| h.candidate.short_channel_id().is_some())
3655 {
3656 let target = hop.candidate.target().expect("target is defined when short_channel_id is defined");
3657 let maybe_announced_channel = if let CandidateRouteHop::PublicHop(_) = hop.candidate {
3658 true
3660 } else if let CandidateRouteHop::FirstHop(first_hop) = &hop.candidate {
3661 first_hop.details.is_announced
3663 } else {
3664 network_graph.node(&target).map_or(false, |hop_node|
3669 hop_node.channels.iter().any(|scid| network_graph.channel(*scid)
3670 .map_or(false, |c| c.as_directed_from(&hop.candidate.source()).is_some()))
3671 )
3672 };
3673
3674 hops.push(RouteHop {
3675 pubkey: PublicKey::from_slice(target.as_slice()).map_err(|_| "A PublicKey in NetworkGraph is invalid!")?,
3676 node_features: node_features.clone(),
3677 short_channel_id: hop.candidate.short_channel_id().unwrap(),
3678 channel_features: hop.candidate.features(),
3679 fee_msat: hop.fee_msat,
3680 cltv_expiry_delta: hop.candidate.cltv_expiry_delta(),
3681 maybe_announced_channel,
3682 });
3683 }
3684 let mut final_cltv_delta = final_cltv_expiry_delta;
3685 let blinded_tail = payment_path.hops.last().and_then(|(h, _)| {
3686 if let Some(blinded_path) = h.candidate.blinded_path() {
3687 final_cltv_delta = h.candidate.cltv_expiry_delta();
3688 Some(BlindedTail {
3689 trampoline_hops: vec![],
3691 hops: blinded_path.blinded_hops().to_vec(),
3692 blinding_point: blinded_path.blinding_point(),
3693 excess_final_cltv_expiry_delta: 0,
3694 final_value_msat: h.fee_msat,
3695 })
3696 } else { None }
3697 });
3698 hops.iter_mut().rev().fold(final_cltv_delta, |prev_cltv_expiry_delta, hop| {
3701 core::mem::replace(&mut hop.cltv_expiry_delta, prev_cltv_expiry_delta)
3702 });
3703
3704 paths.push(Path { hops, blinded_tail });
3705 }
3706 debug_assert!(paths.len() <= payment_params.max_path_count.into());
3708
3709 if let Some(node_features) = payment_params.payee.node_features() {
3710 for path in paths.iter_mut() {
3711 path.hops.last_mut().unwrap().node_features = node_features.clone();
3712 }
3713 }
3714
3715 let route = Route { paths, route_params: Some(route_params.clone()) };
3716
3717 if let Some(max_total_routing_fee_msat) = route_params.max_total_routing_fee_msat {
3719 if route.get_total_fees() > max_total_routing_fee_msat {
3720 return Err("Failed to find route that adheres to the maximum total fee limit");
3721 }
3722 }
3723
3724 log_info!(logger, "Got route: {}", log_route!(route));
3725 Ok(route)
3726}
3727
3728#[rustfmt::skip]
3733fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters,
3734 network_graph: &ReadOnlyNetworkGraph, random_seed_bytes: &[u8; 32]
3735) {
3736 let network_channels = network_graph.channels();
3737 let network_nodes = network_graph.nodes();
3738
3739 for path in route.paths.iter_mut() {
3740 let mut shadow_ctlv_expiry_delta_offset: u32 = 0;
3741
3742 let mut nodes_to_avoid: [NodeId; 3] = [NodeId::from_pubkey(&path.hops.last().unwrap().pubkey),
3745 NodeId::from_pubkey(&path.hops.get(path.hops.len().saturating_sub(2)).unwrap().pubkey),
3746 NodeId::from_pubkey(&path.hops.get(path.hops.len().saturating_sub(3)).unwrap().pubkey)];
3747
3748 let mut cur_hop: Option<NodeId> = None;
3750 let mut path_nonce = [0u8; 12];
3751 if let Some(starting_hop) = path.hops.iter().rev()
3752 .find(|h| network_nodes.contains_key(&NodeId::from_pubkey(&h.pubkey))) {
3753 cur_hop = Some(NodeId::from_pubkey(&starting_hop.pubkey));
3754 path_nonce.copy_from_slice(&cur_hop.unwrap().as_slice()[..12]);
3755 }
3756
3757 let mut prng = ChaCha20::new(random_seed_bytes, &path_nonce);
3759 let mut random_path_bytes = [0u8; ::core::mem::size_of::<usize>()];
3760
3761 prng.process_in_place(&mut random_path_bytes);
3763 let random_walk_length = usize::from_be_bytes(random_path_bytes).wrapping_rem(3).wrapping_add(1);
3764
3765 for random_hop in 0..random_walk_length {
3766 let mut random_hop_offset = MEDIAN_HOP_CLTV_EXPIRY_DELTA;
3769
3770 if let Some(cur_node_id) = cur_hop {
3771 if let Some(cur_node) = network_nodes.get(&cur_node_id) {
3772 prng.process_in_place(&mut random_path_bytes);
3774 if let Some(random_channel) = usize::from_be_bytes(random_path_bytes)
3775 .checked_rem(cur_node.channels.len())
3776 .and_then(|index| cur_node.channels.get(index))
3777 .and_then(|id| network_channels.get(id)) {
3778 random_channel.as_directed_from(&cur_node_id).map(|(dir_info, next_id)| {
3779 if !nodes_to_avoid.iter().any(|x| x == next_id) {
3780 nodes_to_avoid[random_hop] = *next_id;
3781 random_hop_offset = dir_info.direction().cltv_expiry_delta.into();
3782 cur_hop = Some(*next_id);
3783 }
3784 });
3785 }
3786 }
3787 }
3788
3789 shadow_ctlv_expiry_delta_offset = shadow_ctlv_expiry_delta_offset
3790 .checked_add(random_hop_offset)
3791 .unwrap_or(shadow_ctlv_expiry_delta_offset);
3792 }
3793
3794 const MAX_SHADOW_CLTV_EXPIRY_DELTA_OFFSET: u32 = 3*144;
3796 shadow_ctlv_expiry_delta_offset = cmp::min(shadow_ctlv_expiry_delta_offset, MAX_SHADOW_CLTV_EXPIRY_DELTA_OFFSET);
3797
3798 let path_total_cltv_expiry_delta: u32 = path.hops.iter().map(|h| h.cltv_expiry_delta).sum();
3801 let mut max_path_offset = payment_params.max_total_cltv_expiry_delta - path_total_cltv_expiry_delta;
3802 max_path_offset = cmp::max(
3803 max_path_offset - (max_path_offset % MEDIAN_HOP_CLTV_EXPIRY_DELTA),
3804 max_path_offset % MEDIAN_HOP_CLTV_EXPIRY_DELTA);
3805 shadow_ctlv_expiry_delta_offset = cmp::min(shadow_ctlv_expiry_delta_offset, max_path_offset);
3806
3807 if let Some(tail) = path.blinded_tail.as_mut() {
3809 tail.excess_final_cltv_expiry_delta = tail.excess_final_cltv_expiry_delta
3810 .checked_add(shadow_ctlv_expiry_delta_offset).unwrap_or(tail.excess_final_cltv_expiry_delta);
3811 }
3812 if let Some(last_hop) = path.hops.last_mut() {
3813 last_hop.cltv_expiry_delta = last_hop.cltv_expiry_delta
3814 .checked_add(shadow_ctlv_expiry_delta_offset).unwrap_or(last_hop.cltv_expiry_delta);
3815 }
3816 }
3817}
3818
3819#[rustfmt::skip]
3824pub fn build_route_from_hops<L: Deref, GL: Deref>(
3825 our_node_pubkey: &PublicKey, hops: &[PublicKey], route_params: &RouteParameters,
3826 network_graph: &NetworkGraph<GL>, logger: L, random_seed_bytes: &[u8; 32]
3827) -> Result<Route, &'static str>
3828where L::Target: Logger, GL::Target: Logger {
3829 let graph_lock = network_graph.read_only();
3830 let mut route = build_route_from_hops_internal(our_node_pubkey, hops, &route_params,
3831 &graph_lock, logger, random_seed_bytes)?;
3832 add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes);
3833 Ok(route)
3834}
3835
3836#[rustfmt::skip]
3837fn build_route_from_hops_internal<L: Deref>(
3838 our_node_pubkey: &PublicKey, hops: &[PublicKey], route_params: &RouteParameters,
3839 network_graph: &ReadOnlyNetworkGraph, logger: L, random_seed_bytes: &[u8; 32],
3840) -> Result<Route, &'static str> where L::Target: Logger {
3841
3842 struct HopScorer {
3843 our_node_id: NodeId,
3844 hop_ids: [Option<NodeId>; MAX_PATH_LENGTH_ESTIMATE as usize],
3845 }
3846
3847 impl ScoreLookUp for HopScorer {
3848 type ScoreParams = ();
3849 fn channel_penalty_msat(&self, candidate: &CandidateRouteHop,
3850 _usage: ChannelUsage, _score_params: &Self::ScoreParams) -> u64
3851 {
3852 let mut cur_id = self.our_node_id;
3853 for i in 0..self.hop_ids.len() {
3854 if let Some(next_id) = self.hop_ids[i] {
3855 if cur_id == candidate.source() && Some(next_id) == candidate.target() {
3856 return 0;
3857 }
3858 cur_id = next_id;
3859 } else {
3860 break;
3861 }
3862 }
3863 u64::max_value()
3864 }
3865 }
3866
3867 impl<'a> Writeable for HopScorer {
3868 #[inline]
3869 #[rustfmt::skip]
3870 fn write<W: Writer>(&self, _w: &mut W) -> Result<(), io::Error> {
3871 unreachable!();
3872 }
3873 }
3874
3875 if hops.len() > MAX_PATH_LENGTH_ESTIMATE.into() {
3876 return Err("Cannot build a route exceeding the maximum path length.");
3877 }
3878
3879 let our_node_id = NodeId::from_pubkey(our_node_pubkey);
3880 let mut hop_ids = [None; MAX_PATH_LENGTH_ESTIMATE as usize];
3881 for i in 0..hops.len() {
3882 hop_ids[i] = Some(NodeId::from_pubkey(&hops[i]));
3883 }
3884
3885 let scorer = HopScorer { our_node_id, hop_ids };
3886
3887 get_route(our_node_pubkey, route_params, network_graph, None, logger, &scorer, &Default::default(), random_seed_bytes)
3888}
3889
3890#[cfg(test)]
3891mod tests {
3892 use crate::blinded_path::payment::{BlindedPayInfo, BlindedPaymentPath};
3893 use crate::blinded_path::BlindedHop;
3894 use crate::chain::transaction::OutPoint;
3895 use crate::crypto::chacha20::ChaCha20;
3896 use crate::ln::chan_utils::make_funding_redeemscript;
3897 use crate::ln::channel_state::{ChannelCounterparty, ChannelDetails, ChannelShutdownState};
3898 use crate::ln::channelmanager;
3899 use crate::ln::msgs::{UnsignedChannelUpdate, MAX_VALUE_MSAT};
3900 use crate::ln::types::ChannelId;
3901 use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId, P2PGossipSync};
3902 use crate::routing::router::{
3903 add_random_cltv_offset, build_route_from_hops_internal, default_node_features, get_route,
3904 BlindedTail, CandidateRouteHop, InFlightHtlcs, Path, PaymentParameters, PublicHopCandidate,
3905 Route, RouteHint, RouteHintHop, RouteHop, RouteParameters, RoutingFees,
3906 DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE,
3907 };
3908 use crate::routing::scoring::{
3909 ChannelUsage, FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringDecayParameters,
3910 ProbabilisticScoringFeeParameters, ScoreLookUp,
3911 };
3912 use crate::routing::test_utils::{
3913 add_channel, add_or_update_node, build_graph, build_line_graph, get_nodes,
3914 id_to_feature_flags, update_channel,
3915 };
3916 use crate::routing::utxo::UtxoResult;
3917 use crate::types::features::{BlindedHopFeatures, ChannelFeatures, InitFeatures, NodeFeatures};
3918 use crate::util::config::UserConfig;
3919 #[cfg(c_bindings)]
3920 use crate::util::ser::Writer;
3921 use crate::util::ser::{FixedLengthReader, Readable, ReadableArgs, Writeable};
3922 use crate::util::test_utils as ln_test_utils;
3923
3924 use bitcoin::amount::Amount;
3925 use bitcoin::constants::ChainHash;
3926 use bitcoin::hashes::Hash;
3927 use bitcoin::hex::FromHex;
3928 use bitcoin::network::Network;
3929 use bitcoin::opcodes;
3930 use bitcoin::script::Builder;
3931 use bitcoin::secp256k1::Secp256k1;
3932 use bitcoin::secp256k1::{PublicKey, SecretKey};
3933 use bitcoin::transaction::TxOut;
3934
3935 use crate::io::Cursor;
3936 use crate::prelude::*;
3937 use crate::sync::Arc;
3938
3939 #[rustfmt::skip]
3940 fn get_channel_details(short_channel_id: Option<u64>, node_id: PublicKey,
3941 features: InitFeatures, outbound_capacity_msat: u64) -> ChannelDetails {
3942 #[allow(deprecated)] ChannelDetails {
3944 channel_id: ChannelId::new_zero(),
3945 counterparty: ChannelCounterparty {
3946 features,
3947 node_id,
3948 unspendable_punishment_reserve: 0,
3949 forwarding_info: None,
3950 outbound_htlc_minimum_msat: None,
3951 outbound_htlc_maximum_msat: None,
3952 },
3953 funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
3954 funding_redeem_script: Some(make_funding_redeemscript(
3955 &PublicKey::from_slice(&[2; 33]).unwrap(),
3956 &PublicKey::from_slice(&[2; 33]).unwrap(),
3957 )),
3958 channel_type: None,
3959 short_channel_id,
3960 outbound_scid_alias: None,
3961 inbound_scid_alias: None,
3962 channel_value_satoshis: 0,
3963 user_channel_id: 0,
3964 outbound_capacity_msat,
3965 next_outbound_htlc_limit_msat: outbound_capacity_msat,
3966 next_outbound_htlc_minimum_msat: 0,
3967 inbound_capacity_msat: 42,
3968 unspendable_punishment_reserve: None,
3969 confirmations_required: None,
3970 confirmations: None,
3971 force_close_spend_delay: None,
3972 is_outbound: true, is_channel_ready: true,
3973 is_usable: true, is_announced: true,
3974 inbound_htlc_minimum_msat: None,
3975 inbound_htlc_maximum_msat: None,
3976 config: None,
3977 feerate_sat_per_1000_weight: None,
3978 channel_shutdown_state: Some(ChannelShutdownState::NotShuttingDown),
3979 pending_inbound_htlcs: Vec::new(),
3980 pending_outbound_htlcs: Vec::new(),
3981 }
3982 }
3983
3984 #[rustfmt::skip]
3985 fn dummy_blinded_path(intro_node: PublicKey, payinfo: BlindedPayInfo) -> BlindedPaymentPath {
3986 BlindedPaymentPath::from_blinded_path_and_payinfo(
3987 intro_node, ln_test_utils::pubkey(42),
3988 vec![
3989 BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() },
3990 BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() }
3991 ],
3992 payinfo
3993 )
3994 }
3995
3996 #[rustfmt::skip]
3997 fn dummy_one_hop_blinded_path(intro_node: PublicKey, payinfo: BlindedPayInfo) -> BlindedPaymentPath {
3998 BlindedPaymentPath::from_blinded_path_and_payinfo(
3999 intro_node, ln_test_utils::pubkey(42),
4000 vec![
4001 BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() },
4002 ],
4003 payinfo
4004 )
4005 }
4006
4007 #[test]
4008 #[rustfmt::skip]
4009 fn simple_route_test() {
4010 let (secp_ctx, network_graph, _, _, logger) = build_graph();
4011 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
4012 let mut payment_params = PaymentParameters::from_node_id(nodes[2], 42);
4013 let scorer = ln_test_utils::TestScorer::new();
4014 let random_seed_bytes = [42; 32];
4015
4016 let route_params = RouteParameters::from_payment_params_and_value(
4019 payment_params.clone(), 0);
4020 if let Err(err) = get_route(&our_id,
4021 &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer,
4022 &Default::default(), &random_seed_bytes) {
4023 assert_eq!(err, "Cannot send a payment of 0 msat");
4024 } else { panic!(); }
4025
4026 payment_params.max_path_length = 2;
4027 let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4028 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4029 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4030 assert_eq!(route.paths[0].hops.len(), 2);
4031
4032 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
4033 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
4034 assert_eq!(route.paths[0].hops[0].fee_msat, 100);
4035 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
4036 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
4037 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
4038
4039 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
4040 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
4041 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
4042 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
4043 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4044 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
4045
4046 route_params.payment_params.max_path_length = 1;
4047 get_route(&our_id, &route_params, &network_graph.read_only(), None,
4048 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap_err();
4049 }
4050
4051 #[test]
4052 #[rustfmt::skip]
4053 fn invalid_first_hop_test() {
4054 let (secp_ctx, network_graph, _, _, logger) = build_graph();
4055 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
4056 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
4057 let scorer = ln_test_utils::TestScorer::new();
4058 let random_seed_bytes = [42; 32];
4059
4060 let our_chans = [get_channel_details(Some(2), our_id, InitFeatures::from_le_bytes(vec![0b11]), 100000)];
4063
4064 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4065 if let Err(err) = get_route(&our_id,
4066 &route_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()),
4067 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) {
4068 assert_eq!(err, "First hop cannot have our_node_pubkey as a destination.");
4069 } else { panic!(); }
4070
4071 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4072 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4073 assert_eq!(route.paths[0].hops.len(), 2);
4074 }
4075
4076 #[test]
4077 #[rustfmt::skip]
4078 fn htlc_minimum_test() {
4079 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
4080 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
4081 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
4082 let scorer = ln_test_utils::TestScorer::new();
4083 let random_seed_bytes = [42; 32];
4084
4085 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4089 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4090 short_channel_id: 12,
4091 timestamp: 2,
4092 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4095 htlc_minimum_msat: 0,
4096 htlc_maximum_msat: MAX_VALUE_MSAT,
4097 fee_base_msat: 0,
4098 fee_proportional_millionths: 0,
4099 excess_data: Vec::new()
4100 });
4101 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
4102 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4103 short_channel_id: 3,
4104 timestamp: 2,
4105 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4108 htlc_minimum_msat: 0,
4109 htlc_maximum_msat: MAX_VALUE_MSAT,
4110 fee_base_msat: 0,
4111 fee_proportional_millionths: 0,
4112 excess_data: Vec::new()
4113 });
4114 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
4115 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4116 short_channel_id: 13,
4117 timestamp: 2,
4118 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4121 htlc_minimum_msat: 0,
4122 htlc_maximum_msat: MAX_VALUE_MSAT,
4123 fee_base_msat: 0,
4124 fee_proportional_millionths: 0,
4125 excess_data: Vec::new()
4126 });
4127 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
4128 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4129 short_channel_id: 6,
4130 timestamp: 2,
4131 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4134 htlc_minimum_msat: 0,
4135 htlc_maximum_msat: MAX_VALUE_MSAT,
4136 fee_base_msat: 0,
4137 fee_proportional_millionths: 0,
4138 excess_data: Vec::new()
4139 });
4140 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
4141 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4142 short_channel_id: 7,
4143 timestamp: 2,
4144 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4147 htlc_minimum_msat: 0,
4148 htlc_maximum_msat: MAX_VALUE_MSAT,
4149 fee_base_msat: 0,
4150 fee_proportional_millionths: 0,
4151 excess_data: Vec::new()
4152 });
4153
4154 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4157 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4158 short_channel_id: 2,
4159 timestamp: 3,
4160 message_flags: 1, channel_flags: 0,
4162 cltv_expiry_delta: 0,
4163 htlc_minimum_msat: 200_000_000,
4164 htlc_maximum_msat: MAX_VALUE_MSAT,
4165 fee_base_msat: 0,
4166 fee_proportional_millionths: 0,
4167 excess_data: Vec::new()
4168 });
4169
4170 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
4173 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4174 short_channel_id: 4,
4175 timestamp: 3,
4176 message_flags: 1, channel_flags: 0,
4178 cltv_expiry_delta: 0,
4179 htlc_minimum_msat: 0,
4180 htlc_maximum_msat: 199_999_999,
4181 fee_base_msat: 0,
4182 fee_proportional_millionths: 0,
4183 excess_data: Vec::new()
4184 });
4185
4186 let route_params = RouteParameters::from_payment_params_and_value(
4188 payment_params, 199_999_999);
4189 if let Err(err) = get_route(&our_id,
4190 &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer,
4191 &Default::default(), &random_seed_bytes) {
4192 assert_eq!(err, "Failed to find a path to the given destination");
4193 } else { panic!(); }
4194
4195 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4197 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4198 short_channel_id: 2,
4199 timestamp: 4,
4200 message_flags: 1, channel_flags: 0,
4202 cltv_expiry_delta: 0,
4203 htlc_minimum_msat: 0,
4204 htlc_maximum_msat: MAX_VALUE_MSAT,
4205 fee_base_msat: 0,
4206 fee_proportional_millionths: 0,
4207 excess_data: Vec::new()
4208 });
4209
4210 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4212 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4213 assert_eq!(route.paths[0].hops.len(), 2);
4214 }
4215
4216 #[test]
4217 #[rustfmt::skip]
4218 fn htlc_minimum_overpay_test() {
4219 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
4220 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
4221 let config = UserConfig::default();
4222 let payment_params = PaymentParameters::from_node_id(nodes[2], 42)
4223 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
4224 .unwrap();
4225 let scorer = ln_test_utils::TestScorer::new();
4226 let random_seed_bytes = [42; 32];
4227
4228 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4232 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4233 short_channel_id: 2,
4234 timestamp: 2,
4235 message_flags: 1, channel_flags: 0,
4237 cltv_expiry_delta: 0,
4238 htlc_minimum_msat: 35_000,
4239 htlc_maximum_msat: 40_000,
4240 fee_base_msat: 0,
4241 fee_proportional_millionths: 0,
4242 excess_data: Vec::new()
4243 });
4244 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4245 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4246 short_channel_id: 12,
4247 timestamp: 3,
4248 message_flags: 1, channel_flags: 0,
4250 cltv_expiry_delta: 0,
4251 htlc_minimum_msat: 35_000,
4252 htlc_maximum_msat: 40_000,
4253 fee_base_msat: 0,
4254 fee_proportional_millionths: 0,
4255 excess_data: Vec::new()
4256 });
4257
4258 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
4260 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4261 short_channel_id: 13,
4262 timestamp: 2,
4263 message_flags: 1, channel_flags: 0,
4265 cltv_expiry_delta: 0,
4266 htlc_minimum_msat: 0,
4267 htlc_maximum_msat: MAX_VALUE_MSAT,
4268 fee_base_msat: 0,
4269 fee_proportional_millionths: 0,
4270 excess_data: Vec::new()
4271 });
4272 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
4273 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4274 short_channel_id: 4,
4275 timestamp: 2,
4276 message_flags: 1, channel_flags: 0,
4278 cltv_expiry_delta: 0,
4279 htlc_minimum_msat: 0,
4280 htlc_maximum_msat: MAX_VALUE_MSAT,
4281 fee_base_msat: 0,
4282 fee_proportional_millionths: 0,
4283 excess_data: Vec::new()
4284 });
4285
4286 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4288 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4289 short_channel_id: 1,
4290 timestamp: 3,
4291 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4294 htlc_minimum_msat: 0,
4295 htlc_maximum_msat: MAX_VALUE_MSAT,
4296 fee_base_msat: 0,
4297 fee_proportional_millionths: 0,
4298 excess_data: Vec::new()
4299 });
4300
4301 let mut route_params = RouteParameters::from_payment_params_and_value(
4302 payment_params.clone(), 60_000);
4303 route_params.max_total_routing_fee_msat = Some(15_000);
4304 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4305 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4306 let overpaid_fees = route.paths[0].hops[0].fee_msat + route.paths[1].hops[0].fee_msat;
4308 assert_eq!(overpaid_fees, 15_000);
4310
4311 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4314 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4315 short_channel_id: 12,
4316 timestamp: 4,
4317 message_flags: 1, channel_flags: 0,
4319 cltv_expiry_delta: 0,
4320 htlc_minimum_msat: 65_000,
4321 htlc_maximum_msat: 80_000,
4322 fee_base_msat: 0,
4323 fee_proportional_millionths: 0,
4324 excess_data: Vec::new()
4325 });
4326 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4327 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4328 short_channel_id: 2,
4329 timestamp: 3,
4330 message_flags: 1, channel_flags: 0,
4332 cltv_expiry_delta: 0,
4333 htlc_minimum_msat: 0,
4334 htlc_maximum_msat: MAX_VALUE_MSAT,
4335 fee_base_msat: 0,
4336 fee_proportional_millionths: 0,
4337 excess_data: Vec::new()
4338 });
4339 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
4340 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4341 short_channel_id: 4,
4342 timestamp: 4,
4343 message_flags: 1, channel_flags: 0,
4345 cltv_expiry_delta: 0,
4346 htlc_minimum_msat: 0,
4347 htlc_maximum_msat: MAX_VALUE_MSAT,
4348 fee_base_msat: 0,
4349 fee_proportional_millionths: 100_000,
4350 excess_data: Vec::new()
4351 });
4352
4353 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4354 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4355 assert_eq!(route.paths.len(), 1);
4357 assert_eq!(route.paths[0].hops[0].short_channel_id, 12);
4358 let fees = route.paths[0].hops[0].fee_msat;
4359 assert_eq!(fees, 5_000);
4360
4361 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 50_000);
4362 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4363 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4364 assert_eq!(route.paths.len(), 1);
4367 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
4368 let fees = route.paths[0].hops[0].fee_msat;
4369 assert_eq!(fees, 5_000);
4370 }
4371
4372 #[test]
4373 #[rustfmt::skip]
4374 fn htlc_minimum_recipient_overpay_test() {
4375 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
4376 let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
4377 let config = UserConfig::default();
4378 let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap();
4379 let scorer = ln_test_utils::TestScorer::new();
4380 let random_seed_bytes = [42; 32];
4381
4382 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
4386 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4387 short_channel_id: 13,
4388 timestamp: 2,
4389 message_flags: 1, channel_flags: 3,
4391 cltv_expiry_delta: 0,
4392 htlc_minimum_msat: 0,
4393 htlc_maximum_msat: 0,
4394 fee_base_msat: 0,
4395 fee_proportional_millionths: 0,
4396 excess_data: Vec::new()
4397 });
4398
4399 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
4401 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4402 short_channel_id: 4,
4403 timestamp: 2,
4404 message_flags: 1, channel_flags: 0,
4406 cltv_expiry_delta: 0,
4407 htlc_minimum_msat: 15_000,
4408 htlc_maximum_msat: MAX_VALUE_MSAT,
4409 fee_base_msat: 0,
4410 fee_proportional_millionths: 0,
4411 excess_data: Vec::new()
4412 });
4413
4414 let mut route_params = RouteParameters::from_payment_params_and_value(
4419 payment_params.clone(), 5_000);
4420 route_params.max_total_routing_fee_msat = Some(9_999);
4421 if let Err(err) = get_route(&our_id,
4422 &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer,
4423 &Default::default(), &random_seed_bytes) {
4424 assert_eq!(err, "Failed to find route that adheres to the maximum total fee limit");
4425 } else { panic!(); }
4426
4427 let mut route_params = RouteParameters::from_payment_params_and_value(
4428 payment_params.clone(), 5_000);
4429 route_params.max_total_routing_fee_msat = Some(10_000);
4430 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4431 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4432 assert_eq!(route.get_total_fees(), 10_000);
4433 }
4434
4435 #[test]
4436 #[rustfmt::skip]
4437 fn disable_channels_test() {
4438 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
4439 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
4440 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
4441 let scorer = ln_test_utils::TestScorer::new();
4442 let random_seed_bytes = [42; 32];
4443
4444 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
4446 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4447 short_channel_id: 4,
4448 timestamp: 2,
4449 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4452 htlc_minimum_msat: 0,
4453 htlc_maximum_msat: MAX_VALUE_MSAT,
4454 fee_base_msat: 0,
4455 fee_proportional_millionths: 0,
4456 excess_data: Vec::new()
4457 });
4458 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4459 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4460 short_channel_id: 12,
4461 timestamp: 2,
4462 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4465 htlc_minimum_msat: 0,
4466 htlc_maximum_msat: MAX_VALUE_MSAT,
4467 fee_base_msat: 0,
4468 fee_proportional_millionths: 0,
4469 excess_data: Vec::new()
4470 });
4471
4472 let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4474 if let Err(err) = get_route(&our_id,
4475 &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer,
4476 &Default::default(), &random_seed_bytes) {
4477 assert_eq!(err, "Failed to find a path to the given destination");
4478 } else { panic!(); }
4479
4480 let our_chans = [get_channel_details(Some(42), nodes[7].clone(),
4482 InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
4483 route_params.payment_params.max_path_length = 2;
4484 let route = get_route(&our_id, &route_params, &network_graph.read_only(),
4485 Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
4486 &Default::default(), &random_seed_bytes).unwrap();
4487 assert_eq!(route.paths[0].hops.len(), 2);
4488
4489 assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
4490 assert_eq!(route.paths[0].hops[0].short_channel_id, 42);
4491 assert_eq!(route.paths[0].hops[0].fee_msat, 200);
4492 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (13 << 4) | 1);
4493 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &vec![0b11]); assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &Vec::<u8>::new()); assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
4497 assert_eq!(route.paths[0].hops[1].short_channel_id, 13);
4498 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
4499 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
4500 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4501 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(13));
4502 }
4503
4504 #[test]
4505 #[rustfmt::skip]
4506 fn disable_node_test() {
4507 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
4508 let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
4509 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
4510 let scorer = ln_test_utils::TestScorer::new();
4511 let random_seed_bytes = [42; 32];
4512
4513 let mut unknown_features = NodeFeatures::empty();
4515 unknown_features.set_unknown_feature_required();
4516 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[0], unknown_features.clone(), 1);
4517 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[1], unknown_features.clone(), 1);
4518 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[7], unknown_features.clone(), 1);
4519
4520 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4522 if let Err(err) = get_route(&our_id,
4523 &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer,
4524 &Default::default(), &random_seed_bytes) {
4525 assert_eq!(err, "Failed to find a path to the given destination");
4526 } else { panic!(); }
4527
4528 let our_chans = [get_channel_details(Some(42), nodes[7].clone(),
4530 InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
4531 let route = get_route(&our_id, &route_params, &network_graph.read_only(),
4532 Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
4533 &Default::default(), &random_seed_bytes).unwrap();
4534 assert_eq!(route.paths[0].hops.len(), 2);
4535
4536 assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
4537 assert_eq!(route.paths[0].hops[0].short_channel_id, 42);
4538 assert_eq!(route.paths[0].hops[0].fee_msat, 200);
4539 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (13 << 4) | 1);
4540 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &vec![0b11]); assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &Vec::<u8>::new()); assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
4544 assert_eq!(route.paths[0].hops[1].short_channel_id, 13);
4545 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
4546 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
4547 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4548 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(13));
4549
4550 }
4554
4555 #[test]
4556 #[rustfmt::skip]
4557 fn our_chans_test() {
4558 let (secp_ctx, network_graph, _, _, logger) = build_graph();
4559 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
4560 let scorer = ln_test_utils::TestScorer::new();
4561 let random_seed_bytes = [42; 32];
4562
4563 let payment_params = PaymentParameters::from_node_id(nodes[0], 42);
4565 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4566 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4567 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4568 assert_eq!(route.paths[0].hops.len(), 3);
4569
4570 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
4571 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
4572 assert_eq!(route.paths[0].hops[0].fee_msat, 200);
4573 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
4574 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
4575 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
4576
4577 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
4578 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
4579 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
4580 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (3 << 4) | 2);
4581 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4582 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
4583
4584 assert_eq!(route.paths[0].hops[2].pubkey, nodes[0]);
4585 assert_eq!(route.paths[0].hops[2].short_channel_id, 3);
4586 assert_eq!(route.paths[0].hops[2].fee_msat, 100);
4587 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, 42);
4588 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(1));
4589 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(3));
4590
4591 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
4593 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4594 let our_chans = [get_channel_details(Some(42), nodes[7].clone(),
4595 InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
4596 let route = get_route(&our_id, &route_params, &network_graph.read_only(),
4597 Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
4598 &Default::default(), &random_seed_bytes).unwrap();
4599 assert_eq!(route.paths[0].hops.len(), 2);
4600
4601 assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
4602 assert_eq!(route.paths[0].hops[0].short_channel_id, 42);
4603 assert_eq!(route.paths[0].hops[0].fee_msat, 200);
4604 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (13 << 4) | 1);
4605 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &vec![0b11]);
4606 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &Vec::<u8>::new()); assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
4609 assert_eq!(route.paths[0].hops[1].short_channel_id, 13);
4610 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
4611 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
4612 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4613 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(13));
4614 }
4615
4616 #[rustfmt::skip]
4617 fn last_hops(nodes: &Vec<PublicKey>) -> Vec<RouteHint> {
4618 let zero_fees = RoutingFees {
4619 base_msat: 0,
4620 proportional_millionths: 0,
4621 };
4622 vec![RouteHint(vec![RouteHintHop {
4623 src_node_id: nodes[3],
4624 short_channel_id: 8,
4625 fees: zero_fees,
4626 cltv_expiry_delta: (8 << 4) | 1,
4627 htlc_minimum_msat: None,
4628 htlc_maximum_msat: None,
4629 }
4630 ]), RouteHint(vec![RouteHintHop {
4631 src_node_id: nodes[4],
4632 short_channel_id: 9,
4633 fees: RoutingFees {
4634 base_msat: 1001,
4635 proportional_millionths: 0,
4636 },
4637 cltv_expiry_delta: (9 << 4) | 1,
4638 htlc_minimum_msat: None,
4639 htlc_maximum_msat: None,
4640 }]), RouteHint(vec![RouteHintHop {
4641 src_node_id: nodes[5],
4642 short_channel_id: 10,
4643 fees: zero_fees,
4644 cltv_expiry_delta: (10 << 4) | 1,
4645 htlc_minimum_msat: None,
4646 htlc_maximum_msat: None,
4647 }])]
4648 }
4649
4650 #[rustfmt::skip]
4651 fn last_hops_multi_private_channels(nodes: &Vec<PublicKey>) -> Vec<RouteHint> {
4652 let zero_fees = RoutingFees {
4653 base_msat: 0,
4654 proportional_millionths: 0,
4655 };
4656 vec![RouteHint(vec![RouteHintHop {
4657 src_node_id: nodes[2],
4658 short_channel_id: 5,
4659 fees: RoutingFees {
4660 base_msat: 100,
4661 proportional_millionths: 0,
4662 },
4663 cltv_expiry_delta: (5 << 4) | 1,
4664 htlc_minimum_msat: None,
4665 htlc_maximum_msat: None,
4666 }, RouteHintHop {
4667 src_node_id: nodes[3],
4668 short_channel_id: 8,
4669 fees: zero_fees,
4670 cltv_expiry_delta: (8 << 4) | 1,
4671 htlc_minimum_msat: None,
4672 htlc_maximum_msat: None,
4673 }
4674 ]), RouteHint(vec![RouteHintHop {
4675 src_node_id: nodes[4],
4676 short_channel_id: 9,
4677 fees: RoutingFees {
4678 base_msat: 1001,
4679 proportional_millionths: 0,
4680 },
4681 cltv_expiry_delta: (9 << 4) | 1,
4682 htlc_minimum_msat: None,
4683 htlc_maximum_msat: None,
4684 }]), RouteHint(vec![RouteHintHop {
4685 src_node_id: nodes[5],
4686 short_channel_id: 10,
4687 fees: zero_fees,
4688 cltv_expiry_delta: (10 << 4) | 1,
4689 htlc_minimum_msat: None,
4690 htlc_maximum_msat: None,
4691 }])]
4692 }
4693
4694 #[test]
4695 #[rustfmt::skip]
4696 fn partial_route_hint_test() {
4697 let (secp_ctx, network_graph, _, _, logger) = build_graph();
4698 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
4699 let scorer = ln_test_utils::TestScorer::new();
4700 let random_seed_bytes = [42; 32];
4701
4702 let invalid_last_hop = RouteHint(vec![RouteHintHop {
4708 src_node_id: nodes[6],
4709 short_channel_id: 8,
4710 fees: RoutingFees {
4711 base_msat: 1000,
4712 proportional_millionths: 0,
4713 },
4714 cltv_expiry_delta: (8 << 4) | 1,
4715 htlc_minimum_msat: None,
4716 htlc_maximum_msat: None,
4717 }]);
4718
4719 let mut invalid_last_hops = last_hops_multi_private_channels(&nodes);
4720 invalid_last_hops.push(invalid_last_hop);
4721 {
4722 let payment_params = PaymentParameters::from_node_id(nodes[6], 42)
4723 .with_route_hints(invalid_last_hops).unwrap();
4724 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4725 if let Err(err) = get_route(&our_id,
4726 &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer,
4727 &Default::default(), &random_seed_bytes) {
4728 assert_eq!(err, "Route hint cannot have the payee as the source.");
4729 } else { panic!(); }
4730 }
4731
4732 let mut payment_params = PaymentParameters::from_node_id(nodes[6], 42)
4733 .with_route_hints(last_hops_multi_private_channels(&nodes)).unwrap();
4734 payment_params.max_path_length = 5;
4735 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4736 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4737 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4738 assert_eq!(route.paths[0].hops.len(), 5);
4739
4740 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
4741 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
4742 assert_eq!(route.paths[0].hops[0].fee_msat, 100);
4743 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
4744 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
4745 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
4746
4747 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
4748 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
4749 assert_eq!(route.paths[0].hops[1].fee_msat, 0);
4750 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (6 << 4) | 1);
4751 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4752 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
4753
4754 assert_eq!(route.paths[0].hops[2].pubkey, nodes[4]);
4755 assert_eq!(route.paths[0].hops[2].short_channel_id, 6);
4756 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
4757 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, (11 << 4) | 1);
4758 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(5));
4759 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(6));
4760
4761 assert_eq!(route.paths[0].hops[3].pubkey, nodes[3]);
4762 assert_eq!(route.paths[0].hops[3].short_channel_id, 11);
4763 assert_eq!(route.paths[0].hops[3].fee_msat, 0);
4764 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, (8 << 4) | 1);
4765 assert_eq!(route.paths[0].hops[3].node_features.le_flags(), &id_to_feature_flags(4));
4768 assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &id_to_feature_flags(11));
4769
4770 assert_eq!(route.paths[0].hops[4].pubkey, nodes[6]);
4771 assert_eq!(route.paths[0].hops[4].short_channel_id, 8);
4772 assert_eq!(route.paths[0].hops[4].fee_msat, 100);
4773 assert_eq!(route.paths[0].hops[4].cltv_expiry_delta, 42);
4774 assert_eq!(route.paths[0].hops[4].node_features.le_flags(), default_node_features().le_flags()); assert_eq!(route.paths[0].hops[4].channel_features.le_flags(), &Vec::<u8>::new()); }
4777
4778 #[rustfmt::skip]
4779 fn empty_last_hop(nodes: &Vec<PublicKey>) -> Vec<RouteHint> {
4780 let zero_fees = RoutingFees {
4781 base_msat: 0,
4782 proportional_millionths: 0,
4783 };
4784 vec![RouteHint(vec![RouteHintHop {
4785 src_node_id: nodes[3],
4786 short_channel_id: 8,
4787 fees: zero_fees,
4788 cltv_expiry_delta: (8 << 4) | 1,
4789 htlc_minimum_msat: None,
4790 htlc_maximum_msat: None,
4791 }]), RouteHint(vec![
4792
4793 ]), RouteHint(vec![RouteHintHop {
4794 src_node_id: nodes[5],
4795 short_channel_id: 10,
4796 fees: zero_fees,
4797 cltv_expiry_delta: (10 << 4) | 1,
4798 htlc_minimum_msat: None,
4799 htlc_maximum_msat: None,
4800 }])]
4801 }
4802
4803 #[test]
4804 #[rustfmt::skip]
4805 fn ignores_empty_last_hops_test() {
4806 let (secp_ctx, network_graph, _, _, logger) = build_graph();
4807 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
4808 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(empty_last_hop(&nodes)).unwrap();
4809 let scorer = ln_test_utils::TestScorer::new();
4810 let random_seed_bytes = [42; 32];
4811
4812 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4814 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4815 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4816 assert_eq!(route.paths[0].hops.len(), 5);
4817
4818 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
4819 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
4820 assert_eq!(route.paths[0].hops[0].fee_msat, 100);
4821 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
4822 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
4823 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
4824
4825 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
4826 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
4827 assert_eq!(route.paths[0].hops[1].fee_msat, 0);
4828 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (6 << 4) | 1);
4829 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4830 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
4831
4832 assert_eq!(route.paths[0].hops[2].pubkey, nodes[4]);
4833 assert_eq!(route.paths[0].hops[2].short_channel_id, 6);
4834 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
4835 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, (11 << 4) | 1);
4836 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(5));
4837 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(6));
4838
4839 assert_eq!(route.paths[0].hops[3].pubkey, nodes[3]);
4840 assert_eq!(route.paths[0].hops[3].short_channel_id, 11);
4841 assert_eq!(route.paths[0].hops[3].fee_msat, 0);
4842 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, (8 << 4) | 1);
4843 assert_eq!(route.paths[0].hops[3].node_features.le_flags(), &id_to_feature_flags(4));
4846 assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &id_to_feature_flags(11));
4847
4848 assert_eq!(route.paths[0].hops[4].pubkey, nodes[6]);
4849 assert_eq!(route.paths[0].hops[4].short_channel_id, 8);
4850 assert_eq!(route.paths[0].hops[4].fee_msat, 100);
4851 assert_eq!(route.paths[0].hops[4].cltv_expiry_delta, 42);
4852 assert_eq!(route.paths[0].hops[4].node_features.le_flags(), default_node_features().le_flags()); assert_eq!(route.paths[0].hops[4].channel_features.le_flags(), &Vec::<u8>::new()); }
4855
4856 #[rustfmt::skip]
4859 fn multi_hop_last_hops_hint(hint_hops: [PublicKey; 2]) -> Vec<RouteHint> {
4860 let zero_fees = RoutingFees {
4861 base_msat: 0,
4862 proportional_millionths: 0,
4863 };
4864 vec![RouteHint(vec![RouteHintHop {
4865 src_node_id: hint_hops[0],
4866 short_channel_id: 0xff00,
4867 fees: RoutingFees {
4868 base_msat: 100,
4869 proportional_millionths: 0,
4870 },
4871 cltv_expiry_delta: (5 << 4) | 1,
4872 htlc_minimum_msat: None,
4873 htlc_maximum_msat: None,
4874 }, RouteHintHop {
4875 src_node_id: hint_hops[1],
4876 short_channel_id: 0xff01,
4877 fees: zero_fees,
4878 cltv_expiry_delta: (8 << 4) | 1,
4879 htlc_minimum_msat: None,
4880 htlc_maximum_msat: None,
4881 }])]
4882 }
4883
4884 #[test]
4885 #[rustfmt::skip]
4886 fn multi_hint_last_hops_test() {
4887 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
4888 let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
4889 let last_hops = multi_hop_last_hops_hint([nodes[2], nodes[3]]);
4890 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops.clone()).unwrap();
4891 let scorer = ln_test_utils::TestScorer::new();
4892 let random_seed_bytes = [42; 32];
4893
4894 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
4900 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4901 short_channel_id: 6,
4902 timestamp: 2,
4903 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4906 htlc_minimum_msat: 0,
4907 htlc_maximum_msat: MAX_VALUE_MSAT,
4908 fee_base_msat: 0,
4909 fee_proportional_millionths: 0,
4910 excess_data: Vec::new()
4911 });
4912 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
4913 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4914 short_channel_id: 7,
4915 timestamp: 2,
4916 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4919 htlc_minimum_msat: 0,
4920 htlc_maximum_msat: MAX_VALUE_MSAT,
4921 fee_base_msat: 0,
4922 fee_proportional_millionths: 0,
4923 excess_data: Vec::new()
4924 });
4925
4926 let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4927 route_params.payment_params.max_path_length = 4;
4928 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4929 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4930 assert_eq!(route.paths[0].hops.len(), 4);
4931
4932 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
4933 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
4934 assert_eq!(route.paths[0].hops[0].fee_msat, 200);
4935 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, 65);
4936 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
4937 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
4938
4939 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
4940 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
4941 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
4942 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 81);
4943 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4944 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
4945
4946 assert_eq!(route.paths[0].hops[2].pubkey, nodes[3]);
4947 assert_eq!(route.paths[0].hops[2].short_channel_id, last_hops[0].0[0].short_channel_id);
4948 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
4949 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, 129);
4950 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(4));
4951 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &Vec::<u8>::new()); assert_eq!(route.paths[0].hops[3].pubkey, nodes[6]);
4954 assert_eq!(route.paths[0].hops[3].short_channel_id, last_hops[0].0[1].short_channel_id);
4955 assert_eq!(route.paths[0].hops[3].fee_msat, 100);
4956 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, 42);
4957 assert_eq!(route.paths[0].hops[3].node_features.le_flags(), default_node_features().le_flags()); assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &Vec::<u8>::new()); route_params.payment_params.max_path_length = 3;
4960 get_route(&our_id, &route_params, &network_graph.read_only(), None,
4961 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap_err();
4962 }
4963
4964 #[test]
4965 #[rustfmt::skip]
4966 fn private_multi_hint_last_hops_test() {
4967 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
4968 let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
4969
4970 let non_announced_privkey = SecretKey::from_slice(&<Vec<u8>>::from_hex(&format!("{:02x}", 0xf0).repeat(32)).unwrap()[..]).unwrap();
4971 let non_announced_pubkey = PublicKey::from_secret_key(&secp_ctx, &non_announced_privkey);
4972
4973 let last_hops = multi_hop_last_hops_hint([nodes[2], non_announced_pubkey]);
4974 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops.clone()).unwrap();
4975 let scorer = ln_test_utils::TestScorer::new();
4976 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
4981 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4982 short_channel_id: 6,
4983 timestamp: 2,
4984 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4987 htlc_minimum_msat: 0,
4988 htlc_maximum_msat: MAX_VALUE_MSAT,
4989 fee_base_msat: 0,
4990 fee_proportional_millionths: 0,
4991 excess_data: Vec::new()
4992 });
4993 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
4994 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4995 short_channel_id: 7,
4996 timestamp: 2,
4997 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
5000 htlc_minimum_msat: 0,
5001 htlc_maximum_msat: MAX_VALUE_MSAT,
5002 fee_base_msat: 0,
5003 fee_proportional_millionths: 0,
5004 excess_data: Vec::new()
5005 });
5006
5007 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
5008 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5009 Arc::clone(&logger), &scorer, &Default::default(), &[42u8; 32]).unwrap();
5010 assert_eq!(route.paths[0].hops.len(), 4);
5011
5012 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
5013 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
5014 assert_eq!(route.paths[0].hops[0].fee_msat, 200);
5015 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, 65);
5016 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
5017 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
5018
5019 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
5020 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
5021 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
5022 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 81);
5023 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
5024 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
5025
5026 assert_eq!(route.paths[0].hops[2].pubkey, non_announced_pubkey);
5027 assert_eq!(route.paths[0].hops[2].short_channel_id, last_hops[0].0[0].short_channel_id);
5028 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
5029 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, 129);
5030 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), default_node_features().le_flags()); assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &Vec::<u8>::new()); assert_eq!(route.paths[0].hops[3].pubkey, nodes[6]);
5034 assert_eq!(route.paths[0].hops[3].short_channel_id, last_hops[0].0[1].short_channel_id);
5035 assert_eq!(route.paths[0].hops[3].fee_msat, 100);
5036 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, 42);
5037 assert_eq!(route.paths[0].hops[3].node_features.le_flags(), default_node_features().le_flags()); assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &Vec::<u8>::new()); }
5040
5041 #[rustfmt::skip]
5042 fn last_hops_with_public_channel(nodes: &Vec<PublicKey>) -> Vec<RouteHint> {
5043 let zero_fees = RoutingFees {
5044 base_msat: 0,
5045 proportional_millionths: 0,
5046 };
5047 vec![RouteHint(vec![RouteHintHop {
5048 src_node_id: nodes[4],
5049 short_channel_id: 11,
5050 fees: zero_fees,
5051 cltv_expiry_delta: (11 << 4) | 1,
5052 htlc_minimum_msat: None,
5053 htlc_maximum_msat: None,
5054 }, RouteHintHop {
5055 src_node_id: nodes[3],
5056 short_channel_id: 8,
5057 fees: zero_fees,
5058 cltv_expiry_delta: (8 << 4) | 1,
5059 htlc_minimum_msat: None,
5060 htlc_maximum_msat: None,
5061 }]), RouteHint(vec![RouteHintHop {
5062 src_node_id: nodes[4],
5063 short_channel_id: 9,
5064 fees: RoutingFees {
5065 base_msat: 1001,
5066 proportional_millionths: 0,
5067 },
5068 cltv_expiry_delta: (9 << 4) | 1,
5069 htlc_minimum_msat: None,
5070 htlc_maximum_msat: None,
5071 }]), RouteHint(vec![RouteHintHop {
5072 src_node_id: nodes[5],
5073 short_channel_id: 10,
5074 fees: zero_fees,
5075 cltv_expiry_delta: (10 << 4) | 1,
5076 htlc_minimum_msat: None,
5077 htlc_maximum_msat: None,
5078 }])]
5079 }
5080
5081 #[test]
5082 #[rustfmt::skip]
5083 fn last_hops_with_public_channel_test() {
5084 let (secp_ctx, network_graph, _, _, logger) = build_graph();
5085 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
5086 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops_with_public_channel(&nodes)).unwrap();
5087 let scorer = ln_test_utils::TestScorer::new();
5088 let random_seed_bytes = [42; 32];
5089
5090 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
5094 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5095 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5096 assert_eq!(route.paths[0].hops.len(), 5);
5097
5098 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
5099 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
5100 assert_eq!(route.paths[0].hops[0].fee_msat, 100);
5101 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
5102 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
5103 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
5104
5105 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
5106 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
5107 assert_eq!(route.paths[0].hops[1].fee_msat, 0);
5108 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (6 << 4) | 1);
5109 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
5110 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
5111
5112 assert_eq!(route.paths[0].hops[2].pubkey, nodes[4]);
5113 assert_eq!(route.paths[0].hops[2].short_channel_id, 6);
5114 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
5115 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, (11 << 4) | 1);
5116 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(5));
5117 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(6));
5118
5119 assert_eq!(route.paths[0].hops[3].pubkey, nodes[3]);
5120 assert_eq!(route.paths[0].hops[3].short_channel_id, 11);
5121 assert_eq!(route.paths[0].hops[3].fee_msat, 0);
5122 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, (8 << 4) | 1);
5123 assert_eq!(route.paths[0].hops[3].node_features.le_flags(), &id_to_feature_flags(4));
5126 assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &id_to_feature_flags(11));
5127
5128 assert_eq!(route.paths[0].hops[4].pubkey, nodes[6]);
5129 assert_eq!(route.paths[0].hops[4].short_channel_id, 8);
5130 assert_eq!(route.paths[0].hops[4].fee_msat, 100);
5131 assert_eq!(route.paths[0].hops[4].cltv_expiry_delta, 42);
5132 assert_eq!(route.paths[0].hops[4].node_features.le_flags(), default_node_features().le_flags()); assert_eq!(route.paths[0].hops[4].channel_features.le_flags(), &Vec::<u8>::new()); }
5135
5136 #[test]
5137 #[rustfmt::skip]
5138 fn our_chans_last_hop_connect_test() {
5139 let (secp_ctx, network_graph, _, _, logger) = build_graph();
5140 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
5141 let scorer = ln_test_utils::TestScorer::new();
5142 let random_seed_bytes = [42; 32];
5143
5144 let our_chans = [get_channel_details(Some(42), nodes[3].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
5146 let mut last_hops = last_hops(&nodes);
5147 let payment_params = PaymentParameters::from_node_id(nodes[6], 42)
5148 .with_route_hints(last_hops.clone()).unwrap();
5149 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
5150 let route = get_route(&our_id, &route_params, &network_graph.read_only(),
5151 Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
5152 &Default::default(), &random_seed_bytes).unwrap();
5153 assert_eq!(route.paths[0].hops.len(), 2);
5154
5155 assert_eq!(route.paths[0].hops[0].pubkey, nodes[3]);
5156 assert_eq!(route.paths[0].hops[0].short_channel_id, 42);
5157 assert_eq!(route.paths[0].hops[0].fee_msat, 0);
5158 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (8 << 4) | 1);
5159 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &vec![0b11]);
5160 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &Vec::<u8>::new()); assert_eq!(route.paths[0].hops[1].pubkey, nodes[6]);
5163 assert_eq!(route.paths[0].hops[1].short_channel_id, 8);
5164 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
5165 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
5166 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), default_node_features().le_flags()); assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &Vec::<u8>::new()); last_hops[0].0[0].fees.base_msat = 1000;
5170
5171 let payment_params = PaymentParameters::from_node_id(nodes[6], 42)
5173 .with_route_hints(last_hops).unwrap();
5174 let route_params = RouteParameters::from_payment_params_and_value(
5175 payment_params.clone(), 100);
5176 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5177 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5178 assert_eq!(route.paths[0].hops.len(), 4);
5179
5180 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
5181 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
5182 assert_eq!(route.paths[0].hops[0].fee_msat, 200); assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
5184 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
5185 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
5186
5187 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
5188 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
5189 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
5190 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (7 << 4) | 1);
5191 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
5192 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
5193
5194 assert_eq!(route.paths[0].hops[2].pubkey, nodes[5]);
5195 assert_eq!(route.paths[0].hops[2].short_channel_id, 7);
5196 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
5197 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, (10 << 4) | 1);
5198 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(6));
5201 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(7));
5202
5203 assert_eq!(route.paths[0].hops[3].pubkey, nodes[6]);
5204 assert_eq!(route.paths[0].hops[3].short_channel_id, 10);
5205 assert_eq!(route.paths[0].hops[3].fee_msat, 100);
5206 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, 42);
5207 assert_eq!(route.paths[0].hops[3].node_features.le_flags(), default_node_features().le_flags()); assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &Vec::<u8>::new()); let route_params = RouteParameters::from_payment_params_and_value(payment_params, 2000);
5212 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5213 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5214 assert_eq!(route.paths[0].hops.len(), 5);
5215
5216 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
5217 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
5218 assert_eq!(route.paths[0].hops[0].fee_msat, 3000);
5219 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
5220 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
5221 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
5222
5223 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
5224 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
5225 assert_eq!(route.paths[0].hops[1].fee_msat, 0);
5226 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (6 << 4) | 1);
5227 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
5228 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
5229
5230 assert_eq!(route.paths[0].hops[2].pubkey, nodes[4]);
5231 assert_eq!(route.paths[0].hops[2].short_channel_id, 6);
5232 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
5233 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, (11 << 4) | 1);
5234 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(5));
5235 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(6));
5236
5237 assert_eq!(route.paths[0].hops[3].pubkey, nodes[3]);
5238 assert_eq!(route.paths[0].hops[3].short_channel_id, 11);
5239 assert_eq!(route.paths[0].hops[3].fee_msat, 1000);
5240 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, (8 << 4) | 1);
5241 assert_eq!(route.paths[0].hops[3].node_features.le_flags(), &id_to_feature_flags(4));
5244 assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &id_to_feature_flags(11));
5245
5246 assert_eq!(route.paths[0].hops[4].pubkey, nodes[6]);
5247 assert_eq!(route.paths[0].hops[4].short_channel_id, 8);
5248 assert_eq!(route.paths[0].hops[4].fee_msat, 2000);
5249 assert_eq!(route.paths[0].hops[4].cltv_expiry_delta, 42);
5250 assert_eq!(route.paths[0].hops[4].node_features.le_flags(), default_node_features().le_flags()); assert_eq!(route.paths[0].hops[4].channel_features.le_flags(), &Vec::<u8>::new()); }
5253
5254 #[rustfmt::skip]
5255 fn do_unannounced_path_test(last_hop_htlc_max: Option<u64>, last_hop_fee_prop: u32, outbound_capacity_msat: u64, route_val: u64) -> Result<Route, &'static str> {
5256 let source_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&<Vec<u8>>::from_hex(&format!("{:02}", 41).repeat(32)).unwrap()[..]).unwrap());
5257 let middle_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&<Vec<u8>>::from_hex(&format!("{:02}", 42).repeat(32)).unwrap()[..]).unwrap());
5258 let target_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&<Vec<u8>>::from_hex(&format!("{:02}", 43).repeat(32)).unwrap()[..]).unwrap());
5259
5260 let last_hops = RouteHint(vec![RouteHintHop {
5262 src_node_id: middle_node_id,
5263 short_channel_id: 8,
5264 fees: RoutingFees {
5265 base_msat: 1000,
5266 proportional_millionths: last_hop_fee_prop,
5267 },
5268 cltv_expiry_delta: (8 << 4) | 1,
5269 htlc_minimum_msat: None,
5270 htlc_maximum_msat: last_hop_htlc_max,
5271 }]);
5272 let payment_params = PaymentParameters::from_node_id(target_node_id, 42).with_route_hints(vec![last_hops]).unwrap();
5273 let our_chans = [get_channel_details(Some(42), middle_node_id, InitFeatures::from_le_bytes(vec![0b11]), outbound_capacity_msat)];
5274 let scorer = ln_test_utils::TestScorer::new();
5275 let random_seed_bytes = [42; 32];
5276 let logger = ln_test_utils::TestLogger::new();
5277 let network_graph = NetworkGraph::new(Network::Testnet, &logger);
5278 let route_params = RouteParameters::from_payment_params_and_value(payment_params, route_val);
5279 let route = get_route(&source_node_id, &route_params, &network_graph.read_only(),
5280 Some(&our_chans.iter().collect::<Vec<_>>()), &logger, &scorer, &Default::default(),
5281 &random_seed_bytes);
5282 route
5283 }
5284
5285 #[test]
5286 #[rustfmt::skip]
5287 fn unannounced_path_test() {
5288 let route = do_unannounced_path_test(None, 1, 2000000, 1000000).unwrap();
5292
5293 let middle_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&<Vec<u8>>::from_hex(&format!("{:02}", 42).repeat(32)).unwrap()[..]).unwrap());
5294 let target_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&<Vec<u8>>::from_hex(&format!("{:02}", 43).repeat(32)).unwrap()[..]).unwrap());
5295 assert_eq!(route.paths[0].hops.len(), 2);
5296
5297 assert_eq!(route.paths[0].hops[0].pubkey, middle_node_id);
5298 assert_eq!(route.paths[0].hops[0].short_channel_id, 42);
5299 assert_eq!(route.paths[0].hops[0].fee_msat, 1001);
5300 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (8 << 4) | 1);
5301 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &[0b11]);
5302 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &[0; 0]); assert_eq!(route.paths[0].hops[1].pubkey, target_node_id);
5305 assert_eq!(route.paths[0].hops[1].short_channel_id, 8);
5306 assert_eq!(route.paths[0].hops[1].fee_msat, 1000000);
5307 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
5308 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), default_node_features().le_flags()); assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &[0; 0]); }
5311
5312 #[test]
5313 #[rustfmt::skip]
5314 fn overflow_unannounced_path_test_liquidity_underflow() {
5315 assert!(do_unannounced_path_test(Some(21_000_000_0000_0000_000), 0, 21_000_000_0000_0000_000, 21_000_000_0000_0000_000).is_err());
5322 }
5323
5324 #[test]
5325 #[rustfmt::skip]
5326 fn overflow_unannounced_path_test_feerate_overflow() {
5327 assert!(do_unannounced_path_test(Some(21_000_000_0000_0000_000), 50000, 21_000_000_0000_0000_000, 21_000_000_0000_0000_000).is_err());
5330 }
5331
5332 #[test]
5333 #[rustfmt::skip]
5334 fn available_amount_while_routing_test() {
5335 let (secp_ctx, network_graph, gossip_sync, chain_monitor, logger) = build_graph();
5338 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
5339 let scorer = ln_test_utils::TestScorer::new();
5340 let random_seed_bytes = [42; 32];
5341 let config = UserConfig::default();
5342 let payment_params = PaymentParameters::from_node_id(nodes[2], 42)
5343 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
5344 .unwrap();
5345
5346 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5351 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5352 short_channel_id: 2,
5353 timestamp: 2,
5354 message_flags: 1, channel_flags: 2,
5356 cltv_expiry_delta: 0,
5357 htlc_minimum_msat: 0,
5358 htlc_maximum_msat: 100_000,
5359 fee_base_msat: 0,
5360 fee_proportional_millionths: 0,
5361 excess_data: Vec::new()
5362 });
5363 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5364 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5365 short_channel_id: 12,
5366 timestamp: 2,
5367 message_flags: 1, channel_flags: 2,
5369 cltv_expiry_delta: 0,
5370 htlc_minimum_msat: 0,
5371 htlc_maximum_msat: 100_000,
5372 fee_base_msat: 0,
5373 fee_proportional_millionths: 0,
5374 excess_data: Vec::new()
5375 });
5376
5377 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5380 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5381 short_channel_id: 1,
5382 timestamp: 2,
5383 message_flags: 1, channel_flags: 0,
5385 cltv_expiry_delta: 0,
5386 htlc_minimum_msat: 0,
5387 htlc_maximum_msat: 1_000_000_000,
5388 fee_base_msat: 0,
5389 fee_proportional_millionths: 0,
5390 excess_data: Vec::new()
5391 });
5392
5393 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5396 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5397 short_channel_id: 3,
5398 timestamp: 2,
5399 message_flags: 1, channel_flags: 0,
5401 cltv_expiry_delta: 0,
5402 htlc_minimum_msat: 0,
5403 htlc_maximum_msat: 250_000_000,
5404 fee_base_msat: 0,
5405 fee_proportional_millionths: 0,
5406 excess_data: Vec::new()
5407 });
5408
5409 {
5410 let route_params = RouteParameters::from_payment_params_and_value(
5412 payment_params.clone(), 250_000_001);
5413 if let Err(err) = get_route(
5414 &our_id, &route_params, &network_graph.read_only(), None,
5415 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) {
5416 assert_eq!(err, "Failed to find a sufficient route to the given destination");
5417 } else { panic!(); }
5418 }
5419
5420 {
5421 let route_params = RouteParameters::from_payment_params_and_value(
5423 payment_params.clone(), 250_000_000);
5424 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5425 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5426 assert_eq!(route.paths.len(), 1);
5427 let path = route.paths.last().unwrap();
5428 assert_eq!(path.hops.len(), 2);
5429 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
5430 assert_eq!(path.final_value_msat(), 250_000_000);
5431 }
5432
5433 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5436 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5437 short_channel_id: 1,
5438 timestamp: 3,
5439 message_flags: 1, channel_flags: 2,
5441 cltv_expiry_delta: 0,
5442 htlc_minimum_msat: 0,
5443 htlc_maximum_msat: 1_000_000_000,
5444 fee_base_msat: 0,
5445 fee_proportional_millionths: 0,
5446 excess_data: Vec::new()
5447 });
5448
5449 let our_chans = [get_channel_details(Some(42), nodes[0].clone(), InitFeatures::from_le_bytes(vec![0b11]), 200_000_000)];
5451
5452 {
5453 let route_params = RouteParameters::from_payment_params_and_value(
5455 payment_params.clone(), 200_000_001);
5456 if let Err(err) = get_route(
5457 &our_id, &route_params, &network_graph.read_only(),
5458 Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
5459 &Default::default(), &random_seed_bytes) {
5460 assert_eq!(err, "Failed to find a sufficient route to the given destination");
5461 } else { panic!(); }
5462 }
5463
5464 {
5465 let route_params = RouteParameters::from_payment_params_and_value(
5467 payment_params.clone(), 200_000_000);
5468 let route = get_route(&our_id, &route_params, &network_graph.read_only(),
5469 Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
5470 &Default::default(), &random_seed_bytes).unwrap();
5471 assert_eq!(route.paths.len(), 1);
5472 let path = route.paths.last().unwrap();
5473 assert_eq!(path.hops.len(), 2);
5474 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
5475 assert_eq!(path.final_value_msat(), 200_000_000);
5476 }
5477
5478 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5480 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5481 short_channel_id: 1,
5482 timestamp: 4,
5483 message_flags: 1, channel_flags: 0,
5485 cltv_expiry_delta: 0,
5486 htlc_minimum_msat: 0,
5487 htlc_maximum_msat: 1_000_000_000,
5488 fee_base_msat: 0,
5489 fee_proportional_millionths: 0,
5490 excess_data: Vec::new()
5491 });
5492
5493
5494 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5496 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5497 short_channel_id: 3,
5498 timestamp: 3,
5499 message_flags: 1, channel_flags: 0,
5501 cltv_expiry_delta: 0,
5502 htlc_minimum_msat: 0,
5503 htlc_maximum_msat: 15_000,
5504 fee_base_msat: 0,
5505 fee_proportional_millionths: 0,
5506 excess_data: Vec::new()
5507 });
5508
5509 {
5510 let route_params = RouteParameters::from_payment_params_and_value(
5512 payment_params.clone(), 15_001);
5513 if let Err(err) = get_route(
5514 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
5515 &scorer, &Default::default(), &random_seed_bytes) {
5516 assert_eq!(err, "Failed to find a sufficient route to the given destination");
5517 } else { panic!(); }
5518 }
5519
5520 {
5521 let route_params = RouteParameters::from_payment_params_and_value(
5523 payment_params.clone(), 15_000);
5524 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5525 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5526 assert_eq!(route.paths.len(), 1);
5527 let path = route.paths.last().unwrap();
5528 assert_eq!(path.hops.len(), 2);
5529 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
5530 assert_eq!(path.final_value_msat(), 15_000);
5531 }
5532
5533 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5538 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5539 short_channel_id: 3,
5540 timestamp: 4,
5541 message_flags: 1, channel_flags: 2,
5543 cltv_expiry_delta: 0,
5544 htlc_minimum_msat: 0,
5545 htlc_maximum_msat: MAX_VALUE_MSAT,
5546 fee_base_msat: 0,
5547 fee_proportional_millionths: 0,
5548 excess_data: Vec::new()
5549 });
5550
5551 let good_script = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2)
5552 .push_slice(&PublicKey::from_secret_key(&secp_ctx, &privkeys[0]).serialize())
5553 .push_slice(&PublicKey::from_secret_key(&secp_ctx, &privkeys[2]).serialize())
5554 .push_opcode(opcodes::all::OP_PUSHNUM_2)
5555 .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_p2wsh();
5556
5557 *chain_monitor.utxo_ret.lock().unwrap() =
5558 UtxoResult::Sync(Ok(TxOut { value: Amount::from_sat(15), script_pubkey: good_script.clone() }));
5559 gossip_sync.add_utxo_lookup(Some(chain_monitor));
5560
5561 add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 333);
5562 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5563 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5564 short_channel_id: 333,
5565 timestamp: 1,
5566 message_flags: 1, channel_flags: 0,
5568 cltv_expiry_delta: (3 << 4) | 1,
5569 htlc_minimum_msat: 0,
5570 htlc_maximum_msat: 15_000,
5571 fee_base_msat: 0,
5572 fee_proportional_millionths: 0,
5573 excess_data: Vec::new()
5574 });
5575 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
5576 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5577 short_channel_id: 333,
5578 timestamp: 1,
5579 message_flags: 1, channel_flags: 1,
5581 cltv_expiry_delta: (3 << 4) | 2,
5582 htlc_minimum_msat: 0,
5583 htlc_maximum_msat: 15_000,
5584 fee_base_msat: 100,
5585 fee_proportional_millionths: 0,
5586 excess_data: Vec::new()
5587 });
5588
5589 {
5590 let route_params = RouteParameters::from_payment_params_and_value(
5592 payment_params.clone(), 15_001);
5593 if let Err(err) = get_route(
5594 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
5595 &scorer, &Default::default(), &random_seed_bytes) {
5596 assert_eq!(err, "Failed to find a sufficient route to the given destination");
5597 } else { panic!(); }
5598 }
5599
5600 {
5601 let route_params = RouteParameters::from_payment_params_and_value(
5603 payment_params.clone(), 15_000);
5604 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5605 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5606 assert_eq!(route.paths.len(), 1);
5607 let path = route.paths.last().unwrap();
5608 assert_eq!(path.hops.len(), 2);
5609 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
5610 assert_eq!(path.final_value_msat(), 15_000);
5611 }
5612
5613 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5615 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5616 short_channel_id: 333,
5617 timestamp: 6,
5618 message_flags: 1, channel_flags: 0,
5620 cltv_expiry_delta: 0,
5621 htlc_minimum_msat: 0,
5622 htlc_maximum_msat: 10_000,
5623 fee_base_msat: 0,
5624 fee_proportional_millionths: 0,
5625 excess_data: Vec::new()
5626 });
5627
5628 {
5629 let route_params = RouteParameters::from_payment_params_and_value(
5631 payment_params.clone(), 10_001);
5632 if let Err(err) = get_route(
5633 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
5634 &scorer, &Default::default(), &random_seed_bytes) {
5635 assert_eq!(err, "Failed to find a sufficient route to the given destination");
5636 } else { panic!(); }
5637 }
5638
5639 {
5640 let route_params = RouteParameters::from_payment_params_and_value(
5642 payment_params.clone(), 10_000);
5643 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5644 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5645 assert_eq!(route.paths.len(), 1);
5646 let path = route.paths.last().unwrap();
5647 assert_eq!(path.hops.len(), 2);
5648 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
5649 assert_eq!(path.final_value_msat(), 10_000);
5650 }
5651 }
5652
5653 #[test]
5654 #[rustfmt::skip]
5655 fn available_liquidity_last_hop_test() {
5656 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
5659 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
5660 let scorer = ln_test_utils::TestScorer::new();
5661 let random_seed_bytes = [42; 32];
5662 let config = UserConfig::default();
5663 let payment_params = PaymentParameters::from_node_id(nodes[3], 42)
5664 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
5665 .unwrap();
5666
5667 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5673 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5674 short_channel_id: 2,
5675 timestamp: 2,
5676 message_flags: 1, channel_flags: 2,
5678 cltv_expiry_delta: 0,
5679 htlc_minimum_msat: 0,
5680 htlc_maximum_msat: 100_000,
5681 fee_base_msat: 0,
5682 fee_proportional_millionths: 0,
5683 excess_data: Vec::new()
5684 });
5685 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
5686 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5687 short_channel_id: 7,
5688 timestamp: 2,
5689 message_flags: 1, channel_flags: 2,
5691 cltv_expiry_delta: 0,
5692 htlc_minimum_msat: 0,
5693 htlc_maximum_msat: 100_000,
5694 fee_base_msat: 0,
5695 fee_proportional_millionths: 0,
5696 excess_data: Vec::new()
5697 });
5698
5699 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5702 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5703 short_channel_id: 12,
5704 timestamp: 2,
5705 message_flags: 1, channel_flags: 0,
5707 cltv_expiry_delta: 0,
5708 htlc_minimum_msat: 0,
5709 htlc_maximum_msat: 100_000,
5710 fee_base_msat: 0,
5711 fee_proportional_millionths: 0,
5712 excess_data: Vec::new()
5713 });
5714 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
5715 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5716 short_channel_id: 13,
5717 timestamp: 2,
5718 message_flags: 1, channel_flags: 0,
5720 cltv_expiry_delta: 0,
5721 htlc_minimum_msat: 0,
5722 htlc_maximum_msat: 100_000,
5723 fee_base_msat: 0,
5724 fee_proportional_millionths: 0,
5725 excess_data: Vec::new()
5726 });
5727
5728 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
5729 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5730 short_channel_id: 6,
5731 timestamp: 2,
5732 message_flags: 1, channel_flags: 0,
5734 cltv_expiry_delta: 0,
5735 htlc_minimum_msat: 0,
5736 htlc_maximum_msat: 50_000,
5737 fee_base_msat: 0,
5738 fee_proportional_millionths: 0,
5739 excess_data: Vec::new()
5740 });
5741 update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
5742 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5743 short_channel_id: 11,
5744 timestamp: 2,
5745 message_flags: 1, channel_flags: 0,
5747 cltv_expiry_delta: 0,
5748 htlc_minimum_msat: 0,
5749 htlc_maximum_msat: 100_000,
5750 fee_base_msat: 0,
5751 fee_proportional_millionths: 0,
5752 excess_data: Vec::new()
5753 });
5754 {
5755 let route_params = RouteParameters::from_payment_params_and_value(
5757 payment_params.clone(), 60_000);
5758 if let Err(err) = get_route(
5759 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
5760 &scorer, &Default::default(), &random_seed_bytes) {
5761 assert_eq!(err, "Failed to find a sufficient route to the given destination");
5762 } else { panic!(); }
5763 }
5764
5765 {
5766 let route_params = RouteParameters::from_payment_params_and_value(
5768 payment_params.clone(), 49_000);
5769 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5770 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5771 assert_eq!(route.paths.len(), 1);
5772 let mut total_amount_paid_msat = 0;
5773 for path in &route.paths {
5774 assert_eq!(path.hops.len(), 4);
5775 assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]);
5776 total_amount_paid_msat += path.final_value_msat();
5777 }
5778 assert_eq!(total_amount_paid_msat, 49_000);
5779 }
5780
5781 {
5782 let route_params = RouteParameters::from_payment_params_and_value(
5784 payment_params, 50_000);
5785 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5786 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5787 assert_eq!(route.paths.len(), 1);
5788 let mut total_amount_paid_msat = 0;
5789 for path in &route.paths {
5790 assert_eq!(path.hops.len(), 4);
5791 assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]);
5792 total_amount_paid_msat += path.final_value_msat();
5793 }
5794 assert_eq!(total_amount_paid_msat, 50_000);
5795 }
5796 }
5797
5798 #[test]
5799 #[rustfmt::skip]
5800 fn ignore_fee_first_hop_test() {
5801 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
5802 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
5803 let scorer = ln_test_utils::TestScorer::new();
5804 let random_seed_bytes = [42; 32];
5805 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
5806
5807 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5809 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5810 short_channel_id: 1,
5811 timestamp: 2,
5812 message_flags: 1, channel_flags: 0,
5814 cltv_expiry_delta: 0,
5815 htlc_minimum_msat: 0,
5816 htlc_maximum_msat: 100_000,
5817 fee_base_msat: 1_000_000,
5818 fee_proportional_millionths: 0,
5819 excess_data: Vec::new()
5820 });
5821 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5822 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5823 short_channel_id: 3,
5824 timestamp: 2,
5825 message_flags: 1, channel_flags: 0,
5827 cltv_expiry_delta: 0,
5828 htlc_minimum_msat: 0,
5829 htlc_maximum_msat: 50_000,
5830 fee_base_msat: 0,
5831 fee_proportional_millionths: 0,
5832 excess_data: Vec::new()
5833 });
5834
5835 {
5836 let route_params = RouteParameters::from_payment_params_and_value(
5837 payment_params, 50_000);
5838 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5839 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5840 assert_eq!(route.paths.len(), 1);
5841 let mut total_amount_paid_msat = 0;
5842 for path in &route.paths {
5843 assert_eq!(path.hops.len(), 2);
5844 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
5845 total_amount_paid_msat += path.final_value_msat();
5846 }
5847 assert_eq!(total_amount_paid_msat, 50_000);
5848 }
5849 }
5850
5851 #[test]
5852 #[rustfmt::skip]
5853 fn simple_mpp_route_test() {
5854 let (secp_ctx, _, _, _, _) = build_graph();
5855 let (_, _, _, nodes) = get_nodes(&secp_ctx);
5856 let config = UserConfig::default();
5857 let clear_payment_params = PaymentParameters::from_node_id(nodes[2], 42)
5858 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
5859 .unwrap();
5860 do_simple_mpp_route_test(clear_payment_params);
5861
5862 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
5864 let blinded_payinfo = BlindedPayInfo { fee_base_msat: 0,
5866 fee_proportional_millionths: 0,
5867 htlc_minimum_msat: 0,
5868 htlc_maximum_msat: 0,
5869 cltv_expiry_delta: 0,
5870 features: BlindedHopFeatures::empty(),
5871 };
5872 let blinded_path = dummy_one_hop_blinded_path(nodes[2], blinded_payinfo.clone());
5873 let one_hop_blinded_payment_params = PaymentParameters::blinded(vec![blinded_path.clone()])
5874 .with_bolt12_features(bolt12_features.clone()).unwrap();
5875 do_simple_mpp_route_test(one_hop_blinded_payment_params.clone());
5876
5877 let mut node_0_payinfo = blinded_payinfo.clone();
5879 node_0_payinfo.htlc_maximum_msat = 50_000;
5880 let blinded_path_node_0 = dummy_blinded_path(nodes[0], node_0_payinfo);
5881
5882 let mut node_7_payinfo = blinded_payinfo.clone();
5883 node_7_payinfo.htlc_maximum_msat = 60_000;
5884 let blinded_path_node_7 = dummy_blinded_path(nodes[7], node_7_payinfo);
5885
5886 let mut node_1_payinfo = blinded_payinfo;
5887 node_1_payinfo.htlc_maximum_msat = 180_000;
5888 let blinded_path_node_1 = dummy_blinded_path(nodes[1], node_1_payinfo);
5889
5890 let two_hop_blinded_payment_params = PaymentParameters::blinded(
5891 vec![blinded_path_node_0, blinded_path_node_7, blinded_path_node_1])
5892 .with_bolt12_features(bolt12_features).unwrap();
5893 do_simple_mpp_route_test(two_hop_blinded_payment_params);
5894 }
5895
5896 #[rustfmt::skip]
5897 fn do_simple_mpp_route_test(payment_params: PaymentParameters) {
5898 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
5899 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
5900 let scorer = ln_test_utils::TestScorer::new();
5901 let random_seed_bytes = [42; 32];
5902
5903 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5913 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5914 short_channel_id: 1,
5915 timestamp: 2,
5916 message_flags: 1, channel_flags: 0,
5918 cltv_expiry_delta: 0,
5919 htlc_minimum_msat: 0,
5920 htlc_maximum_msat: 100_000,
5921 fee_base_msat: 0,
5922 fee_proportional_millionths: 0,
5923 excess_data: Vec::new()
5924 });
5925 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5926 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5927 short_channel_id: 3,
5928 timestamp: 2,
5929 message_flags: 1, channel_flags: 0,
5931 cltv_expiry_delta: 0,
5932 htlc_minimum_msat: 0,
5933 htlc_maximum_msat: 50_000,
5934 fee_base_msat: 0,
5935 fee_proportional_millionths: 0,
5936 excess_data: Vec::new()
5937 });
5938
5939 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5942 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5943 short_channel_id: 12,
5944 timestamp: 2,
5945 message_flags: 1, channel_flags: 0,
5947 cltv_expiry_delta: 0,
5948 htlc_minimum_msat: 0,
5949 htlc_maximum_msat: 60_000,
5950 fee_base_msat: 0,
5951 fee_proportional_millionths: 0,
5952 excess_data: Vec::new()
5953 });
5954 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
5955 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5956 short_channel_id: 13,
5957 timestamp: 2,
5958 message_flags: 1, channel_flags: 0,
5960 cltv_expiry_delta: 0,
5961 htlc_minimum_msat: 0,
5962 htlc_maximum_msat: 60_000,
5963 fee_base_msat: 0,
5964 fee_proportional_millionths: 0,
5965 excess_data: Vec::new()
5966 });
5967
5968 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5971 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5972 short_channel_id: 2,
5973 timestamp: 2,
5974 message_flags: 1, channel_flags: 0,
5976 cltv_expiry_delta: 0,
5977 htlc_minimum_msat: 0,
5978 htlc_maximum_msat: 200_000,
5979 fee_base_msat: 0,
5980 fee_proportional_millionths: 0,
5981 excess_data: Vec::new()
5982 });
5983 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
5984 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5985 short_channel_id: 4,
5986 timestamp: 2,
5987 message_flags: 1, channel_flags: 0,
5989 cltv_expiry_delta: 0,
5990 htlc_minimum_msat: 0,
5991 htlc_maximum_msat: 180_000,
5992 fee_base_msat: 0,
5993 fee_proportional_millionths: 0,
5994 excess_data: Vec::new()
5995 });
5996
5997 {
5998 let route_params = RouteParameters::from_payment_params_and_value(
6000 payment_params.clone(), 300_000);
6001 if let Err(err) = get_route(
6002 &our_id, &route_params, &network_graph.read_only(), None,
6003 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) {
6004 assert_eq!(err, "Failed to find a sufficient route to the given destination");
6005 } else { panic!(); }
6006 }
6007
6008 {
6009 let zero_payment_params = payment_params.clone().with_max_path_count(0);
6011 let route_params = RouteParameters::from_payment_params_and_value(
6012 zero_payment_params, 100);
6013 if let Err(err) = get_route(
6014 &our_id, &route_params, &network_graph.read_only(), None,
6015 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) {
6016 assert_eq!(err, "Can't find a route with no paths allowed.");
6017 } else { panic!(); }
6018 }
6019
6020 {
6021 let fail_payment_params = payment_params.clone().with_max_path_count(3);
6025 let route_params = RouteParameters::from_payment_params_and_value(
6026 fail_payment_params, 250_000);
6027 if let Err(err) = get_route(
6028 &our_id, &route_params, &network_graph.read_only(), None,
6029 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) {
6030 assert_eq!(err, "Failed to find a sufficient route to the given destination");
6031 } else { panic!(); }
6032 }
6033
6034 {
6035 let route_params = RouteParameters::from_payment_params_and_value(
6038 payment_params.clone(), 250_000);
6039 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6040 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6041 assert_eq!(route.paths.len(), 3);
6042 let mut total_amount_paid_msat = 0;
6043 for path in &route.paths {
6044 if let Some(bt) = &path.blinded_tail {
6045 assert_eq!(path.hops.len() + if bt.hops.len() == 1 { 0 } else { 1 }, 2);
6046 } else {
6047 assert_eq!(path.hops.len(), 2);
6048 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
6049 }
6050 total_amount_paid_msat += path.final_value_msat();
6051 }
6052 assert_eq!(total_amount_paid_msat, 250_000);
6053 }
6054
6055 {
6056 let route_params = RouteParameters::from_payment_params_and_value(
6058 payment_params.clone(), 290_000);
6059 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6060 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6061 assert_eq!(route.paths.len(), 3);
6062 let mut total_amount_paid_msat = 0;
6063 for path in &route.paths {
6064 if payment_params.payee.blinded_route_hints().len() != 0 {
6065 assert!(path.blinded_tail.is_some()) } else { assert!(path.blinded_tail.is_none()) }
6066 if let Some(bt) = &path.blinded_tail {
6067 assert_eq!(path.hops.len() + if bt.hops.len() == 1 { 0 } else { 1 }, 2);
6068 if bt.hops.len() > 1 {
6069 let network_graph = network_graph.read_only();
6070 assert_eq!(
6071 NodeId::from_pubkey(&path.hops.last().unwrap().pubkey),
6072 payment_params.payee.blinded_route_hints().iter()
6073 .find(|p| p.payinfo.htlc_maximum_msat == path.final_value_msat())
6074 .and_then(|p| p.public_introduction_node_id(&network_graph))
6075 .copied()
6076 .unwrap()
6077 );
6078 } else {
6079 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
6080 }
6081 } else {
6082 assert_eq!(path.hops.len(), 2);
6083 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
6084 }
6085 total_amount_paid_msat += path.final_value_msat();
6086 }
6087 assert_eq!(total_amount_paid_msat, 290_000);
6088 }
6089 }
6090
6091 #[test]
6092 fn mpp_tests() {
6093 let secp_ctx = Secp256k1::new();
6094 let (_, _, _, nodes) = get_nodes(&secp_ctx);
6095 {
6096 let route = do_mpp_route_tests(180_000).unwrap();
6099 assert_eq!(route.paths.len(), 2);
6100
6101 let mut total_value_transferred_msat = 0;
6102 let mut total_paid_msat = 0;
6103 for path in &route.paths {
6104 assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]);
6105 total_value_transferred_msat += path.final_value_msat();
6106 for hop in &path.hops {
6107 total_paid_msat += hop.fee_msat;
6108 }
6109 }
6110 assert_eq!(total_value_transferred_msat, 180_000);
6112 let total_fees_paid = total_paid_msat - total_value_transferred_msat;
6113 assert_eq!(total_fees_paid, 0);
6114 }
6115 {
6116 let route = do_mpp_route_tests(300_000).unwrap();
6119 assert_eq!(route.paths.len(), 3);
6120
6121 let mut total_amount_paid_msat = 0;
6122 for path in &route.paths {
6123 assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]);
6124 total_amount_paid_msat += path.final_value_msat();
6125 }
6126 assert_eq!(total_amount_paid_msat, 300_000);
6127 }
6128 assert!(do_mpp_route_tests(300_001).is_err());
6130 }
6131
6132 #[rustfmt::skip]
6133 fn do_mpp_route_tests(amt: u64) -> Result<Route, &'static str> {
6134 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
6135 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
6136 let scorer = ln_test_utils::TestScorer::new();
6137 let random_seed_bytes = [42; 32];
6138 let config = UserConfig::default();
6139 let payment_params = PaymentParameters::from_node_id(nodes[3], 42)
6140 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
6141 .unwrap();
6142
6143 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
6152 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6153 short_channel_id: 7,
6154 timestamp: 2,
6155 message_flags: 1, channel_flags: 2,
6157 cltv_expiry_delta: 0,
6158 htlc_minimum_msat: 0,
6159 htlc_maximum_msat: 100_000,
6160 fee_base_msat: 0,
6161 fee_proportional_millionths: 0,
6162 excess_data: Vec::new()
6163 });
6164 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
6165 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6166 short_channel_id: 4,
6167 timestamp: 2,
6168 message_flags: 1, channel_flags: 2,
6170 cltv_expiry_delta: 0,
6171 htlc_minimum_msat: 0,
6172 htlc_maximum_msat: 100_000,
6173 fee_base_msat: 0,
6174 fee_proportional_millionths: 0,
6175 excess_data: Vec::new()
6176 });
6177
6178 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6180 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6181 short_channel_id: 1,
6182 timestamp: 2,
6183 message_flags: 1, channel_flags: 0,
6185 cltv_expiry_delta: 0,
6186 htlc_minimum_msat: 0,
6187 htlc_maximum_msat: 100_000,
6188 fee_base_msat: 0,
6189 fee_proportional_millionths: 0,
6190 excess_data: Vec::new()
6191 });
6192 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
6193 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6194 short_channel_id: 3,
6195 timestamp: 2,
6196 message_flags: 1, channel_flags: 0,
6198 cltv_expiry_delta: 0,
6199 htlc_minimum_msat: 0,
6200 htlc_maximum_msat: 100_000,
6201 fee_base_msat: 0,
6202 fee_proportional_millionths: 0,
6203 excess_data: Vec::new()
6204 });
6205
6206 add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(16)), 16);
6207 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
6208 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6209 short_channel_id: 16,
6210 timestamp: 2,
6211 message_flags: 1, channel_flags: 0,
6213 cltv_expiry_delta: 0,
6214 htlc_minimum_msat: 0,
6215 htlc_maximum_msat: 100_000,
6216 fee_base_msat: 1_000,
6217 fee_proportional_millionths: 0,
6218 excess_data: Vec::new()
6219 });
6220 update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
6221 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6222 short_channel_id: 16,
6223 timestamp: 2,
6224 message_flags: 1, channel_flags: 3, cltv_expiry_delta: 0,
6227 htlc_minimum_msat: 0,
6228 htlc_maximum_msat: 100_000,
6229 fee_base_msat: 1_000,
6230 fee_proportional_millionths: 0,
6231 excess_data: Vec::new()
6232 });
6233
6234 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6238 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6239 short_channel_id: 12,
6240 timestamp: 2,
6241 message_flags: 1, channel_flags: 0,
6243 cltv_expiry_delta: 0,
6244 htlc_minimum_msat: 0,
6245 htlc_maximum_msat: 100_000,
6246 fee_base_msat: 0,
6247 fee_proportional_millionths: 0,
6248 excess_data: Vec::new()
6249 });
6250 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
6251 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6252 short_channel_id: 13,
6253 timestamp: 2,
6254 message_flags: 1, channel_flags: 0,
6256 cltv_expiry_delta: 0,
6257 htlc_minimum_msat: 0,
6258 htlc_maximum_msat: 100_000,
6259 fee_base_msat: 0,
6260 fee_proportional_millionths: 0,
6261 excess_data: Vec::new()
6262 });
6263
6264 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
6265 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6266 short_channel_id: 6,
6267 timestamp: 2,
6268 message_flags: 1, channel_flags: 0,
6270 cltv_expiry_delta: 0,
6271 htlc_minimum_msat: 0,
6272 htlc_maximum_msat: 200_000,
6273 fee_base_msat: 0,
6274 fee_proportional_millionths: 0,
6275 excess_data: Vec::new()
6276 });
6277 update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
6278 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6279 short_channel_id: 11,
6280 timestamp: 2,
6281 message_flags: 1, channel_flags: 0,
6283 cltv_expiry_delta: 0,
6284 htlc_minimum_msat: 0,
6285 htlc_maximum_msat: 200_000,
6286 fee_base_msat: 0,
6287 fee_proportional_millionths: 0,
6288 excess_data: Vec::new()
6289 });
6290
6291 let route_params = RouteParameters::from_payment_params_and_value(
6296 payment_params, amt);
6297 let res = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6298 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes);
6299 res
6300 }
6301
6302 #[test]
6303 #[rustfmt::skip]
6304 fn fees_on_mpp_route_test() {
6305 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
6309 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
6310 let scorer = ln_test_utils::TestScorer::new();
6311 let random_seed_bytes = [42; 32];
6312 let config = UserConfig::default();
6313 let payment_params = PaymentParameters::from_node_id(nodes[3], 42)
6314 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
6315 .unwrap();
6316
6317 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6328 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6329 short_channel_id: 2,
6330 timestamp: 2,
6331 message_flags: 1, channel_flags: 2,
6333 cltv_expiry_delta: 0,
6334 htlc_minimum_msat: 0,
6335 htlc_maximum_msat: 100_000,
6336 fee_base_msat: 0,
6337 fee_proportional_millionths: 0,
6338 excess_data: Vec::new()
6339 });
6340
6341 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
6342 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6343 short_channel_id: 7,
6344 timestamp: 2,
6345 message_flags: 1, channel_flags: 2,
6347 cltv_expiry_delta: 0,
6348 htlc_minimum_msat: 0,
6349 htlc_maximum_msat: 100_000,
6350 fee_base_msat: 0,
6351 fee_proportional_millionths: 0,
6352 excess_data: Vec::new()
6353 });
6354
6355 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6357 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6358 short_channel_id: 1,
6359 timestamp: 2,
6360 message_flags: 1, channel_flags: 0,
6362 cltv_expiry_delta: 0,
6363 htlc_minimum_msat: 0,
6364 htlc_maximum_msat: 100_000,
6365 fee_base_msat: 0,
6366 fee_proportional_millionths: 0,
6367 excess_data: Vec::new()
6368 });
6369 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
6370 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6371 short_channel_id: 3,
6372 timestamp: 2,
6373 message_flags: 1, channel_flags: 0,
6375 cltv_expiry_delta: 0,
6376 htlc_minimum_msat: 0,
6377 htlc_maximum_msat: 100_000,
6378 fee_base_msat: 0,
6379 fee_proportional_millionths: 0,
6380 excess_data: Vec::new()
6381 });
6382
6383 add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
6384 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
6385 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6386 short_channel_id: 5,
6387 timestamp: 2,
6388 message_flags: 1, channel_flags: 0,
6390 cltv_expiry_delta: 0,
6391 htlc_minimum_msat: 0,
6392 htlc_maximum_msat: 100_000,
6393 fee_base_msat: 0,
6394 fee_proportional_millionths: 0,
6395 excess_data: Vec::new()
6396 });
6397 update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
6398 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6399 short_channel_id: 5,
6400 timestamp: 2,
6401 message_flags: 1, channel_flags: 3, cltv_expiry_delta: 0,
6404 htlc_minimum_msat: 0,
6405 htlc_maximum_msat: 100_000,
6406 fee_base_msat: 0,
6407 fee_proportional_millionths: 0,
6408 excess_data: Vec::new()
6409 });
6410
6411 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6422 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6423 short_channel_id: 12,
6424 timestamp: 2,
6425 message_flags: 1, channel_flags: 0,
6427 cltv_expiry_delta: 0,
6428 htlc_minimum_msat: 0,
6429 htlc_maximum_msat: 250_000,
6430 fee_base_msat: 0,
6431 fee_proportional_millionths: 0,
6432 excess_data: Vec::new()
6433 });
6434 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
6435 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6436 short_channel_id: 13,
6437 timestamp: 2,
6438 message_flags: 1, channel_flags: 0,
6440 cltv_expiry_delta: 0,
6441 htlc_minimum_msat: 0,
6442 htlc_maximum_msat: MAX_VALUE_MSAT,
6443 fee_base_msat: 0,
6444 fee_proportional_millionths: 0,
6445 excess_data: Vec::new()
6446 });
6447
6448 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
6449 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6450 short_channel_id: 6,
6451 timestamp: 2,
6452 message_flags: 1, channel_flags: 0,
6454 cltv_expiry_delta: 0,
6455 htlc_minimum_msat: 0,
6456 htlc_maximum_msat: MAX_VALUE_MSAT,
6457 fee_base_msat: 150_000,
6458 fee_proportional_millionths: 0,
6459 excess_data: Vec::new()
6460 });
6461 update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
6462 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6463 short_channel_id: 11,
6464 timestamp: 2,
6465 message_flags: 1, channel_flags: 0,
6467 cltv_expiry_delta: 0,
6468 htlc_minimum_msat: 0,
6469 htlc_maximum_msat: MAX_VALUE_MSAT,
6470 fee_base_msat: 0,
6471 fee_proportional_millionths: 0,
6472 excess_data: Vec::new()
6473 });
6474
6475 {
6476 let route_params = RouteParameters::from_payment_params_and_value(
6478 payment_params.clone(), 210_000);
6479 if let Err(err) = get_route(
6480 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
6481 &scorer, &Default::default(), &random_seed_bytes) {
6482 assert_eq!(err, "Failed to find a sufficient route to the given destination");
6483 } else { panic!(); }
6484 }
6485
6486 {
6487 let route_params = RouteParameters { payment_params: payment_params.clone(), final_value_msat: 200_000,
6489 max_total_routing_fee_msat: Some(149_999) };
6490 if let Err(err) = get_route(
6491 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
6492 &scorer, &Default::default(), &random_seed_bytes) {
6493 assert_eq!(err, "Failed to find a sufficient route to the given destination");
6494 } else { panic!(); }
6495 }
6496
6497 {
6498 let route_params = RouteParameters { payment_params: payment_params.clone(), final_value_msat: 200_000,
6500 max_total_routing_fee_msat: Some(150_000) };
6501 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6502 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6503 assert_eq!(route.paths.len(), 2);
6504
6505 let mut total_amount_paid_msat = 0;
6506 for path in &route.paths {
6507 assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]);
6508 total_amount_paid_msat += path.final_value_msat();
6509 }
6510 assert_eq!(total_amount_paid_msat, 200_000);
6511 assert_eq!(route.get_total_fees(), 150_000);
6512 }
6513 }
6514
6515 #[test]
6516 #[rustfmt::skip]
6517 fn mpp_with_last_hops() {
6518 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
6532 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
6533 let scorer = ln_test_utils::TestScorer::new();
6534 let random_seed_bytes = [42; 32];
6535 let config = UserConfig::default();
6536 let payment_params = PaymentParameters::from_node_id(PublicKey::from_slice(&[2; 33]).unwrap(), 42)
6537 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap()
6538 .with_route_hints(vec![RouteHint(vec![RouteHintHop {
6539 src_node_id: nodes[2],
6540 short_channel_id: 42,
6541 fees: RoutingFees { base_msat: 0, proportional_millionths: 0 },
6542 cltv_expiry_delta: 42,
6543 htlc_minimum_msat: None,
6544 htlc_maximum_msat: None,
6545 }])]).unwrap().with_max_channel_saturation_power_of_half(0);
6546
6547 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6553 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6554 short_channel_id: 1,
6555 timestamp: 2,
6556 message_flags: 1, channel_flags: 0,
6558 cltv_expiry_delta: (5 << 4) | 5,
6559 htlc_minimum_msat: 0,
6560 htlc_maximum_msat: 99_000,
6561 fee_base_msat: u32::max_value(),
6562 fee_proportional_millionths: u32::max_value(),
6563 excess_data: Vec::new()
6564 });
6565 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6566 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6567 short_channel_id: 2,
6568 timestamp: 2,
6569 message_flags: 1, channel_flags: 0,
6571 cltv_expiry_delta: (5 << 4) | 3,
6572 htlc_minimum_msat: 0,
6573 htlc_maximum_msat: 99_000,
6574 fee_base_msat: u32::max_value(),
6575 fee_proportional_millionths: u32::max_value(),
6576 excess_data: Vec::new()
6577 });
6578 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
6579 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6580 short_channel_id: 4,
6581 timestamp: 2,
6582 message_flags: 1, channel_flags: 0,
6584 cltv_expiry_delta: (4 << 4) | 1,
6585 htlc_minimum_msat: 0,
6586 htlc_maximum_msat: MAX_VALUE_MSAT,
6587 fee_base_msat: 1,
6588 fee_proportional_millionths: 0,
6589 excess_data: Vec::new()
6590 });
6591 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
6592 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6593 short_channel_id: 13,
6594 timestamp: 2,
6595 message_flags: 1, channel_flags: 0|2, cltv_expiry_delta: (13 << 4) | 1,
6598 htlc_minimum_msat: 0,
6599 htlc_maximum_msat: MAX_VALUE_MSAT,
6600 fee_base_msat: 0,
6601 fee_proportional_millionths: 2000000,
6602 excess_data: Vec::new()
6603 });
6604
6605 let route_params = RouteParameters::from_payment_params_and_value(
6608 payment_params, 100_000);
6609 let mut route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6610 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6611 assert_eq!(route.paths.len(), 2);
6612 route.paths.sort_by_key(|path| path.hops[0].short_channel_id);
6613 assert_eq!(route.paths[0].hops[0].short_channel_id, 1);
6617 assert_eq!(route.paths[0].hops[0].fee_msat, 0);
6618 assert_eq!(route.paths[0].hops[2].fee_msat, 99_000);
6619 assert_eq!(route.paths[1].hops[0].short_channel_id, 2);
6620 assert_eq!(route.paths[1].hops[0].fee_msat, 1);
6621 assert_eq!(route.paths[1].hops[2].fee_msat, 1_000);
6622 assert_eq!(route.get_total_fees(), 1);
6623 assert_eq!(route.get_total_amount(), 100_000);
6624 }
6625
6626 #[test]
6627 #[rustfmt::skip]
6628 fn drop_lowest_channel_mpp_route_test() {
6629 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
6632 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
6633 let scorer = ln_test_utils::TestScorer::new();
6634 let random_seed_bytes = [42; 32];
6635 let config = UserConfig::default();
6636 let payment_params = PaymentParameters::from_node_id(nodes[2], 42)
6637 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
6638 .unwrap()
6639 .with_max_channel_saturation_power_of_half(0);
6640
6641 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6652 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6653 short_channel_id: 1,
6654 timestamp: 2,
6655 message_flags: 1, channel_flags: 0,
6657 cltv_expiry_delta: 0,
6658 htlc_minimum_msat: 0,
6659 htlc_maximum_msat: 100_000,
6660 fee_base_msat: 0,
6661 fee_proportional_millionths: 0,
6662 excess_data: Vec::new()
6663 });
6664 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
6665 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6666 short_channel_id: 3,
6667 timestamp: 2,
6668 message_flags: 1, channel_flags: 0,
6670 cltv_expiry_delta: 0,
6671 htlc_minimum_msat: 0,
6672 htlc_maximum_msat: 50_000,
6673 fee_base_msat: 100,
6674 fee_proportional_millionths: 0,
6675 excess_data: Vec::new()
6676 });
6677
6678 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6680 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6681 short_channel_id: 12,
6682 timestamp: 2,
6683 message_flags: 1, channel_flags: 0,
6685 cltv_expiry_delta: 0,
6686 htlc_minimum_msat: 0,
6687 htlc_maximum_msat: 60_000,
6688 fee_base_msat: 100,
6689 fee_proportional_millionths: 0,
6690 excess_data: Vec::new()
6691 });
6692 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
6693 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6694 short_channel_id: 13,
6695 timestamp: 2,
6696 message_flags: 1, channel_flags: 0,
6698 cltv_expiry_delta: 0,
6699 htlc_minimum_msat: 0,
6700 htlc_maximum_msat: 60_000,
6701 fee_base_msat: 0,
6702 fee_proportional_millionths: 0,
6703 excess_data: Vec::new()
6704 });
6705
6706 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6708 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6709 short_channel_id: 2,
6710 timestamp: 2,
6711 message_flags: 1, channel_flags: 0,
6713 cltv_expiry_delta: 0,
6714 htlc_minimum_msat: 0,
6715 htlc_maximum_msat: 20_000,
6716 fee_base_msat: 0,
6717 fee_proportional_millionths: 0,
6718 excess_data: Vec::new()
6719 });
6720 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
6721 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6722 short_channel_id: 4,
6723 timestamp: 2,
6724 message_flags: 1, channel_flags: 0,
6726 cltv_expiry_delta: 0,
6727 htlc_minimum_msat: 0,
6728 htlc_maximum_msat: 20_000,
6729 fee_base_msat: 0,
6730 fee_proportional_millionths: 0,
6731 excess_data: Vec::new()
6732 });
6733
6734 {
6735 let route_params = RouteParameters::from_payment_params_and_value(
6737 payment_params.clone(), 150_000);
6738 if let Err(err) = get_route(
6739 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
6740 &scorer, &Default::default(), &random_seed_bytes) {
6741 assert_eq!(err, "Failed to find a sufficient route to the given destination");
6742 } else { panic!(); }
6743 }
6744
6745 {
6746 let route_params = RouteParameters::from_payment_params_and_value(
6749 payment_params.clone(), 125_000);
6750 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6751 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6752 assert_eq!(route.paths.len(), 3);
6753 let mut total_amount_paid_msat = 0;
6754 for path in &route.paths {
6755 assert_eq!(path.hops.len(), 2);
6756 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
6757 total_amount_paid_msat += path.final_value_msat();
6758 }
6759 assert_eq!(total_amount_paid_msat, 125_000);
6760 }
6761
6762 {
6763 let route_params = RouteParameters::from_payment_params_and_value(
6765 payment_params, 90_000);
6766 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6767 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6768 assert_eq!(route.paths.len(), 2);
6769 let mut total_amount_paid_msat = 0;
6770 for path in &route.paths {
6771 assert_eq!(path.hops.len(), 2);
6772 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
6773 total_amount_paid_msat += path.final_value_msat();
6774 }
6775 assert_eq!(total_amount_paid_msat, 90_000);
6776 }
6777 }
6778
6779 #[test]
6780 #[rustfmt::skip]
6781 fn min_criteria_consistency() {
6782 let secp_ctx = Secp256k1::new();
6807 let logger = Arc::new(ln_test_utils::TestLogger::new());
6808 let network = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
6809 let gossip_sync = P2PGossipSync::new(Arc::clone(&network), None, Arc::clone(&logger));
6810 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
6811 let scorer = ln_test_utils::TestScorer::new();
6812 let random_seed_bytes = [42; 32];
6813 let payment_params = PaymentParameters::from_node_id(nodes[6], 42);
6814
6815 add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[1], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6);
6816 for (key, channel_flags) in [(&our_privkey, 0), (&privkeys[1], 3)] {
6817 update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6818 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6819 short_channel_id: 6,
6820 timestamp: 1,
6821 message_flags: 1, channel_flags,
6823 cltv_expiry_delta: (6 << 4) | 0,
6824 htlc_minimum_msat: 0,
6825 htlc_maximum_msat: MAX_VALUE_MSAT,
6826 fee_base_msat: 0,
6827 fee_proportional_millionths: 0,
6828 excess_data: Vec::new()
6829 });
6830 }
6831 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[1], NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0);
6832
6833 add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
6834 for (key, channel_flags) in [(&privkeys[1], 0), (&privkeys[4], 3)] {
6835 update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6836 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6837 short_channel_id: 5,
6838 timestamp: 1,
6839 message_flags: 1, channel_flags,
6841 cltv_expiry_delta: (5 << 4) | 0,
6842 htlc_minimum_msat: 0,
6843 htlc_maximum_msat: MAX_VALUE_MSAT,
6844 fee_base_msat: 100,
6845 fee_proportional_millionths: 0,
6846 excess_data: Vec::new()
6847 });
6848 }
6849 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[4], NodeFeatures::from_le_bytes(id_to_feature_flags(4)), 0);
6850
6851 add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), 4);
6852 for (key, channel_flags) in [(&privkeys[4], 0), (&privkeys[3], 3)] {
6853 update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6854 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6855 short_channel_id: 4,
6856 timestamp: 1,
6857 message_flags: 1, channel_flags,
6859 cltv_expiry_delta: (4 << 4) | 0,
6860 htlc_minimum_msat: 0,
6861 htlc_maximum_msat: MAX_VALUE_MSAT,
6862 fee_base_msat: 0,
6863 fee_proportional_millionths: 0,
6864 excess_data: Vec::new()
6865 });
6866 }
6867 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[3], NodeFeatures::from_le_bytes(id_to_feature_flags(3)), 0);
6868
6869 add_channel(&gossip_sync, &secp_ctx, &privkeys[3], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 3);
6870 for (key, channel_flags) in [(&privkeys[3], 0), (&privkeys[2], 3)] {
6871 update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6872 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6873 short_channel_id: 3,
6874 timestamp: 1,
6875 message_flags: 1, channel_flags,
6877 cltv_expiry_delta: (3 << 4) | 0,
6878 htlc_minimum_msat: 0,
6879 htlc_maximum_msat: MAX_VALUE_MSAT,
6880 fee_base_msat: 0,
6881 fee_proportional_millionths: 0,
6882 excess_data: Vec::new()
6883 });
6884 }
6885 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[2], NodeFeatures::from_le_bytes(id_to_feature_flags(2)), 0);
6886
6887 add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), 2);
6888 for (key, channel_flags) in [(&privkeys[2], 0), (&privkeys[4], 3)] {
6889 update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6890 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6891 short_channel_id: 2,
6892 timestamp: 1,
6893 message_flags: 1, channel_flags,
6895 cltv_expiry_delta: (2 << 4) | 0,
6896 htlc_minimum_msat: 0,
6897 htlc_maximum_msat: MAX_VALUE_MSAT,
6898 fee_base_msat: 0,
6899 fee_proportional_millionths: 0,
6900 excess_data: Vec::new()
6901 });
6902 }
6903
6904 add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[6], ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1);
6905 for (key, channel_flags) in [(&privkeys[4], 0), (&privkeys[6], 3)] {
6906 update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6907 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6908 short_channel_id: 1,
6909 timestamp: 1,
6910 message_flags: 1, channel_flags,
6912 cltv_expiry_delta: (1 << 4) | 0,
6913 htlc_minimum_msat: 100,
6914 htlc_maximum_msat: MAX_VALUE_MSAT,
6915 fee_base_msat: 0,
6916 fee_proportional_millionths: 0,
6917 excess_data: Vec::new()
6918 });
6919 }
6920 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[6], NodeFeatures::from_le_bytes(id_to_feature_flags(6)), 0);
6921
6922 {
6923 let route_params = RouteParameters::from_payment_params_and_value(
6925 payment_params, 10_000);
6926 let route = get_route(&our_id, &route_params, &network.read_only(), None,
6927 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6928 assert_eq!(route.paths.len(), 1);
6929 assert_eq!(route.paths[0].hops.len(), 3);
6930
6931 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
6932 assert_eq!(route.paths[0].hops[0].short_channel_id, 6);
6933 assert_eq!(route.paths[0].hops[0].fee_msat, 100);
6934 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (5 << 4) | 0);
6935 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(1));
6936 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(6));
6937
6938 assert_eq!(route.paths[0].hops[1].pubkey, nodes[4]);
6939 assert_eq!(route.paths[0].hops[1].short_channel_id, 5);
6940 assert_eq!(route.paths[0].hops[1].fee_msat, 0);
6941 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (1 << 4) | 0);
6942 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(4));
6943 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(5));
6944
6945 assert_eq!(route.paths[0].hops[2].pubkey, nodes[6]);
6946 assert_eq!(route.paths[0].hops[2].short_channel_id, 1);
6947 assert_eq!(route.paths[0].hops[2].fee_msat, 10_000);
6948 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, 42);
6949 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(6));
6950 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(1));
6951 }
6952 }
6953
6954 #[test]
6955 #[rustfmt::skip]
6956 fn exact_fee_liquidity_limit() {
6957 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
6961 let (our_privkey, our_id, _, nodes) = get_nodes(&secp_ctx);
6962 let scorer = ln_test_utils::TestScorer::new();
6963 let random_seed_bytes = [42; 32];
6964 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
6965
6966 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6969 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6970 short_channel_id: 2,
6971 timestamp: 2,
6972 message_flags: 1, channel_flags: 0,
6974 cltv_expiry_delta: 0,
6975 htlc_minimum_msat: 0,
6976 htlc_maximum_msat: 85_000,
6977 fee_base_msat: 0,
6978 fee_proportional_millionths: 0,
6979 excess_data: Vec::new()
6980 });
6981
6982 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6983 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6984 short_channel_id: 12,
6985 timestamp: 2,
6986 message_flags: 1, channel_flags: 0,
6988 cltv_expiry_delta: (4 << 4) | 1,
6989 htlc_minimum_msat: 0,
6990 htlc_maximum_msat: 270_000,
6991 fee_base_msat: 0,
6992 fee_proportional_millionths: 1000000,
6993 excess_data: Vec::new()
6994 });
6995
6996 {
6997 let mut route_params = RouteParameters::from_payment_params_and_value(
7000 payment_params, 90_000);
7001 route_params.max_total_routing_fee_msat = Some(90_000*2);
7002 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
7003 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7004 assert_eq!(route.paths.len(), 1);
7005 assert_eq!(route.paths[0].hops.len(), 2);
7006
7007 assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
7008 assert_eq!(route.paths[0].hops[0].short_channel_id, 12);
7009 assert_eq!(route.paths[0].hops[0].fee_msat, 90_000*2);
7010 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (13 << 4) | 1);
7011 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(8));
7012 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(12));
7013
7014 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
7015 assert_eq!(route.paths[0].hops[1].short_channel_id, 13);
7016 assert_eq!(route.paths[0].hops[1].fee_msat, 90_000);
7017 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
7018 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
7019 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(13));
7020 }
7021 }
7022
7023 #[test]
7024 #[rustfmt::skip]
7025 fn htlc_max_reduction_below_min() {
7026 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
7031 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
7032 let scorer = ln_test_utils::TestScorer::new();
7033 let random_seed_bytes = [42; 32];
7034 let config = UserConfig::default();
7035 let payment_params = PaymentParameters::from_node_id(nodes[2], 42)
7036 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
7037 .unwrap();
7038
7039 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
7043 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
7044 short_channel_id: 2,
7045 timestamp: 2,
7046 message_flags: 1, channel_flags: 0,
7048 cltv_expiry_delta: 0,
7049 htlc_minimum_msat: 0,
7050 htlc_maximum_msat: 80_000,
7051 fee_base_msat: 0,
7052 fee_proportional_millionths: 0,
7053 excess_data: Vec::new()
7054 });
7055 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
7056 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
7057 short_channel_id: 4,
7058 timestamp: 2,
7059 message_flags: 1, channel_flags: 0,
7061 cltv_expiry_delta: (4 << 4) | 1,
7062 htlc_minimum_msat: 90_000,
7063 htlc_maximum_msat: MAX_VALUE_MSAT,
7064 fee_base_msat: 0,
7065 fee_proportional_millionths: 0,
7066 excess_data: Vec::new()
7067 });
7068
7069 {
7070 let mut route_params = RouteParameters::from_payment_params_and_value(
7074 payment_params, 90_000);
7075 route_params.max_total_routing_fee_msat = Some(90_000*2);
7076 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
7077 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7078 assert_eq!(route.paths.len(), 1);
7079 assert_eq!(route.paths[0].hops.len(), 2);
7080
7081 assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
7082 assert_eq!(route.paths[0].hops[0].short_channel_id, 12);
7083 assert_eq!(route.paths[0].hops[0].fee_msat, 90_000*2);
7084 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (13 << 4) | 1);
7085 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(8));
7086 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(12));
7087
7088 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
7089 assert_eq!(route.paths[0].hops[1].short_channel_id, 13);
7090 assert_eq!(route.paths[0].hops[1].fee_msat, 90_000);
7091 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
7092 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), channelmanager::provided_bolt11_invoice_features(&config).le_flags());
7093 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(13));
7094 }
7095 }
7096
7097 #[test]
7098 #[rustfmt::skip]
7099 fn multiple_direct_first_hops() {
7100 let secp_ctx = Secp256k1::new();
7107 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7108 let logger = Arc::new(ln_test_utils::TestLogger::new());
7109 let network_graph = NetworkGraph::new(Network::Testnet, Arc::clone(&logger));
7110 let scorer = ln_test_utils::TestScorer::new();
7111 let config = UserConfig::default();
7112 let payment_params = PaymentParameters::from_node_id(nodes[0], 42)
7113 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
7114 .unwrap();
7115 let random_seed_bytes = [42; 32];
7116
7117 {
7118 let route_params = RouteParameters::from_payment_params_and_value(
7119 payment_params.clone(), 100_000);
7120 let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[
7121 &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 200_000),
7122 &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 10_000),
7123 ]), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7124 assert_eq!(route.paths.len(), 1);
7125 assert_eq!(route.paths[0].hops.len(), 1);
7126
7127 assert_eq!(route.paths[0].hops[0].pubkey, nodes[0]);
7128 assert_eq!(route.paths[0].hops[0].short_channel_id, 3);
7129 assert_eq!(route.paths[0].hops[0].fee_msat, 100_000);
7130 }
7131 {
7132 let route_params = RouteParameters::from_payment_params_and_value(
7133 payment_params.clone(), 100_000);
7134 let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[
7135 &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7136 &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7137 ]), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7138 assert_eq!(route.paths.len(), 2);
7139 assert_eq!(route.paths[0].hops.len(), 1);
7140 assert_eq!(route.paths[1].hops.len(), 1);
7141
7142 assert!((route.paths[0].hops[0].short_channel_id == 3 && route.paths[1].hops[0].short_channel_id == 2) ||
7143 (route.paths[0].hops[0].short_channel_id == 2 && route.paths[1].hops[0].short_channel_id == 3));
7144
7145 assert_eq!(route.paths[0].hops[0].pubkey, nodes[0]);
7146 assert_eq!(route.paths[0].hops[0].fee_msat, 50_000);
7147
7148 assert_eq!(route.paths[1].hops[0].pubkey, nodes[0]);
7149 assert_eq!(route.paths[1].hops[0].fee_msat, 50_000);
7150 }
7151
7152 {
7153 let route_params = RouteParameters::from_payment_params_and_value(
7161 payment_params, 100_000);
7162 let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[
7163 &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7164 &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7165 &get_channel_details(Some(5), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7166 &get_channel_details(Some(6), nodes[0], channelmanager::provided_init_features(&config), 300_000),
7167 &get_channel_details(Some(7), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7168 &get_channel_details(Some(8), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7169 &get_channel_details(Some(9), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7170 &get_channel_details(Some(4), nodes[0], channelmanager::provided_init_features(&config), 1_000_000),
7171 ]), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7172 assert_eq!(route.paths.len(), 1);
7173 assert_eq!(route.paths[0].hops.len(), 1);
7174
7175 assert_eq!(route.paths[0].hops[0].pubkey, nodes[0]);
7176 assert_eq!(route.paths[0].hops[0].short_channel_id, 6);
7177 assert_eq!(route.paths[0].hops[0].fee_msat, 100_000);
7178 }
7179 }
7180
7181 #[test]
7182 #[rustfmt::skip]
7183 fn prefers_shorter_route_with_higher_fees() {
7184 let (secp_ctx, network_graph, _, _, logger) = build_graph();
7185 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7186 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap();
7187
7188 let scorer = ln_test_utils::TestScorer::new();
7190 let random_seed_bytes = [42; 32];
7191 let route_params = RouteParameters::from_payment_params_and_value(
7192 payment_params.clone(), 100);
7193 let route = get_route( &our_id, &route_params, &network_graph.read_only(), None,
7194 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7195 let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
7196
7197 assert_eq!(route.get_total_fees(), 100);
7198 assert_eq!(route.get_total_amount(), 100);
7199 assert_eq!(path, vec![2, 4, 6, 11, 8]);
7200
7201 let scorer = FixedPenaltyScorer::with_penalty(100);
7204 let route_params = RouteParameters::from_payment_params_and_value(
7205 payment_params, 100);
7206 let route = get_route( &our_id, &route_params, &network_graph.read_only(), None,
7207 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7208 let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
7209
7210 assert_eq!(route.get_total_fees(), 300);
7211 assert_eq!(route.get_total_amount(), 100);
7212 assert_eq!(path, vec![2, 4, 7, 10]);
7213 }
7214
7215 struct BadChannelScorer {
7216 short_channel_id: u64,
7217 }
7218
7219 #[cfg(c_bindings)]
7220 impl Writeable for BadChannelScorer {
7221 #[rustfmt::skip]
7222 fn write<W: Writer>(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() }
7223 }
7224 impl ScoreLookUp for BadChannelScorer {
7225 type ScoreParams = ();
7226 #[rustfmt::skip]
7227 fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 {
7228 if candidate.short_channel_id() == Some(self.short_channel_id) { u64::max_value() } else { 0 }
7229 }
7230 }
7231
7232 struct BadNodeScorer {
7233 node_id: NodeId,
7234 }
7235
7236 #[cfg(c_bindings)]
7237 impl Writeable for BadNodeScorer {
7238 #[rustfmt::skip]
7239 fn write<W: Writer>(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() }
7240 }
7241
7242 impl ScoreLookUp for BadNodeScorer {
7243 type ScoreParams = ();
7244 #[rustfmt::skip]
7245 fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 {
7246 if candidate.target() == Some(self.node_id) { u64::max_value() } else { 0 }
7247 }
7248 }
7249
7250 #[test]
7251 #[rustfmt::skip]
7252 fn avoids_routing_through_bad_channels_and_nodes() {
7253 let (secp_ctx, network, _, _, logger) = build_graph();
7254 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7255 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap();
7256 let network_graph = network.read_only();
7257
7258 let scorer = ln_test_utils::TestScorer::new();
7260 let random_seed_bytes = [42; 32];
7261 let route_params = RouteParameters::from_payment_params_and_value(
7262 payment_params, 100);
7263 let route = get_route( &our_id, &route_params, &network_graph, None, Arc::clone(&logger),
7264 &scorer, &Default::default(), &random_seed_bytes).unwrap();
7265 let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
7266
7267 assert_eq!(route.get_total_fees(), 100);
7268 assert_eq!(route.get_total_amount(), 100);
7269 assert_eq!(path, vec![2, 4, 6, 11, 8]);
7270
7271 let scorer = BadChannelScorer { short_channel_id: 6 };
7273 let route = get_route( &our_id, &route_params, &network_graph, None, Arc::clone(&logger),
7274 &scorer, &Default::default(), &random_seed_bytes).unwrap();
7275 let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
7276
7277 assert_eq!(route.get_total_fees(), 300);
7278 assert_eq!(route.get_total_amount(), 100);
7279 assert_eq!(path, vec![2, 4, 7, 10]);
7280
7281 let scorer = BadNodeScorer { node_id: NodeId::from_pubkey(&nodes[2]) };
7283 match get_route( &our_id, &route_params, &network_graph, None, Arc::clone(&logger),
7284 &scorer, &Default::default(), &random_seed_bytes) {
7285 Err(err) => {
7286 assert_eq!(err, "Failed to find a path to the given destination");
7287 },
7288 Ok(_) => panic!("Expected error"),
7289 }
7290 }
7291
7292 #[test]
7293 fn total_fees_single_path() {
7294 let route = Route {
7295 paths: vec![Path { hops: vec![
7296 RouteHop {
7297 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
7298 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7299 short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0, maybe_announced_channel: true,
7300 },
7301 RouteHop {
7302 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
7303 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7304 short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0, maybe_announced_channel: true,
7305 },
7306 RouteHop {
7307 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()[..]).unwrap(),
7308 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7309 short_channel_id: 0, fee_msat: 225, cltv_expiry_delta: 0, maybe_announced_channel: true,
7310 },
7311 ], blinded_tail: None }],
7312 route_params: None,
7313 };
7314
7315 assert_eq!(route.get_total_fees(), 250);
7316 assert_eq!(route.get_total_amount(), 225);
7317 }
7318
7319 #[test]
7320 fn total_fees_multi_path() {
7321 let route = Route {
7322 paths: vec![Path { hops: vec![
7323 RouteHop {
7324 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
7325 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7326 short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0, maybe_announced_channel: true,
7327 },
7328 RouteHop {
7329 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
7330 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7331 short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0, maybe_announced_channel: true,
7332 },
7333 ], blinded_tail: None }, Path { hops: vec![
7334 RouteHop {
7335 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
7336 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7337 short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0, maybe_announced_channel: true,
7338 },
7339 RouteHop {
7340 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
7341 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7342 short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0, maybe_announced_channel: true,
7343 },
7344 ], blinded_tail: None }],
7345 route_params: None,
7346 };
7347
7348 assert_eq!(route.get_total_fees(), 200);
7349 assert_eq!(route.get_total_amount(), 300);
7350 }
7351
7352 #[test]
7353 fn total_empty_route_no_panic() {
7354 let route = Route { paths: Vec::new(), route_params: None };
7358
7359 assert_eq!(route.get_total_fees(), 0);
7360 assert_eq!(route.get_total_amount(), 0);
7361 }
7362
7363 #[test]
7364 #[rustfmt::skip]
7365 fn limits_total_cltv_delta() {
7366 let (secp_ctx, network, _, _, logger) = build_graph();
7367 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7368 let network_graph = network.read_only();
7369
7370 let scorer = ln_test_utils::TestScorer::new();
7371
7372 let feasible_max_total_cltv_delta = 1008;
7374 let feasible_payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap()
7375 .with_max_total_cltv_expiry_delta(feasible_max_total_cltv_delta);
7376 let random_seed_bytes = [42; 32];
7377 let route_params = RouteParameters::from_payment_params_and_value(
7378 feasible_payment_params, 100);
7379 let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
7380 &scorer, &Default::default(), &random_seed_bytes).unwrap();
7381 let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
7382 assert_ne!(path.len(), 0);
7383
7384 let fail_max_total_cltv_delta = 23;
7386 let fail_payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap()
7387 .with_max_total_cltv_expiry_delta(fail_max_total_cltv_delta);
7388 let route_params = RouteParameters::from_payment_params_and_value(
7389 fail_payment_params, 100);
7390 match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
7391 &Default::default(), &random_seed_bytes)
7392 {
7393 Err(err) => {
7394 assert_eq!(err, "Failed to find a path to the given destination");
7395 },
7396 Ok(_) => panic!("Expected error"),
7397 }
7398 }
7399
7400 #[test]
7401 #[rustfmt::skip]
7402 fn avoids_recently_failed_paths() {
7403 let (secp_ctx, network, _, _, logger) = build_graph();
7406 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7407 let network_graph = network.read_only();
7408
7409 let scorer = ln_test_utils::TestScorer::new();
7410 let mut payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap()
7411 .with_max_path_count(1);
7412 let random_seed_bytes = [42; 32];
7413
7414 let route_params = RouteParameters::from_payment_params_and_value(
7417 payment_params.clone(), 100);
7418 assert!(get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
7419 &scorer, &Default::default(), &random_seed_bytes).is_ok());
7420 loop {
7421 let route_params = RouteParameters::from_payment_params_and_value(
7422 payment_params.clone(), 100);
7423 if let Ok(route) = get_route(&our_id, &route_params, &network_graph, None,
7424 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes)
7425 {
7426 for chan in route.paths[0].hops.iter() {
7427 assert!(!payment_params.previously_failed_channels.contains(&chan.short_channel_id));
7428 }
7429 let victim = (u64::from_ne_bytes(random_seed_bytes[0..8].try_into().unwrap()) as usize)
7430 % route.paths[0].hops.len();
7431 payment_params.previously_failed_channels.push(route.paths[0].hops[victim].short_channel_id);
7432 } else { break; }
7433 }
7434 }
7435
7436 #[test]
7437 #[rustfmt::skip]
7438 fn limits_path_length() {
7439 let (secp_ctx, network, _, _, logger) = build_line_graph();
7440 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7441 let network_graph = network.read_only();
7442
7443 let scorer = ln_test_utils::TestScorer::new();
7444 let random_seed_bytes = [42; 32];
7445
7446 let feasible_payment_params = PaymentParameters::from_node_id(nodes[18], 0);
7448 let route_params = RouteParameters::from_payment_params_and_value(
7449 feasible_payment_params, 100);
7450 let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
7451 &scorer, &Default::default(), &random_seed_bytes).unwrap();
7452 let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
7453 assert!(path.len() == MAX_PATH_LENGTH_ESTIMATE.into());
7454
7455 let fail_payment_params = PaymentParameters::from_node_id(nodes[19], 0);
7457 let route_params = RouteParameters::from_payment_params_and_value(
7458 fail_payment_params, 100);
7459 match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
7460 &Default::default(), &random_seed_bytes)
7461 {
7462 Err(err) => {
7463 assert_eq!(err, "Failed to find a path to the given destination");
7464 },
7465 Ok(_) => panic!("Expected error"),
7466 }
7467 }
7468
7469 #[test]
7470 #[rustfmt::skip]
7471 fn adds_and_limits_cltv_offset() {
7472 let (secp_ctx, network_graph, _, _, logger) = build_graph();
7473 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7474
7475 let scorer = ln_test_utils::TestScorer::new();
7476
7477 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap();
7478 let random_seed_bytes = [42; 32];
7479 let route_params = RouteParameters::from_payment_params_and_value(
7480 payment_params.clone(), 100);
7481 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
7482 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7483 assert_eq!(route.paths.len(), 1);
7484
7485 let cltv_expiry_deltas_before = route.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::<Vec<u32>>();
7486
7487 let mut route_default = route.clone();
7489 add_random_cltv_offset(&mut route_default, &payment_params, &network_graph.read_only(), &random_seed_bytes);
7490 let cltv_expiry_deltas_default = route_default.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::<Vec<u32>>();
7491 assert_eq!(cltv_expiry_deltas_before.split_last().unwrap().1, cltv_expiry_deltas_default.split_last().unwrap().1);
7492 assert!(cltv_expiry_deltas_default.last() > cltv_expiry_deltas_before.last());
7493 assert!(cltv_expiry_deltas_default.last().unwrap() <= &DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA);
7494
7495 let mut route_limited = route.clone();
7497 let limited_max_total_cltv_expiry_delta = cltv_expiry_deltas_before.iter().sum();
7498 let limited_payment_params = payment_params.with_max_total_cltv_expiry_delta(limited_max_total_cltv_expiry_delta);
7499 add_random_cltv_offset(&mut route_limited, &limited_payment_params, &network_graph.read_only(), &random_seed_bytes);
7500 let cltv_expiry_deltas_limited = route_limited.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::<Vec<u32>>();
7501 assert_eq!(cltv_expiry_deltas_before, cltv_expiry_deltas_limited);
7502 }
7503
7504 #[test]
7505 #[rustfmt::skip]
7506 fn adds_plausible_cltv_offset() {
7507 let (secp_ctx, network, _, _, logger) = build_graph();
7508 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7509 let network_graph = network.read_only();
7510 let network_nodes = network_graph.nodes();
7511 let network_channels = network_graph.channels();
7512 let scorer = ln_test_utils::TestScorer::new();
7513 let payment_params = PaymentParameters::from_node_id(nodes[3], 0);
7514 let random_seed_bytes = [42; 32];
7515
7516 let route_params = RouteParameters::from_payment_params_and_value(
7517 payment_params.clone(), 100);
7518 let mut route = get_route(&our_id, &route_params, &network_graph, None,
7519 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7520 add_random_cltv_offset(&mut route, &payment_params, &network_graph, &random_seed_bytes);
7521
7522 let mut path_plausibility = vec![];
7523
7524 for p in route.paths {
7525 let mut prng = ChaCha20::new(&random_seed_bytes, &[0u8; 12]);
7527 let mut random_bytes = [0u8; ::core::mem::size_of::<usize>()];
7528
7529 prng.process_in_place(&mut random_bytes);
7530 let random_path_index = usize::from_be_bytes(random_bytes).wrapping_rem(p.hops.len());
7531 let observation_point = NodeId::from_pubkey(&p.hops.get(random_path_index).unwrap().pubkey);
7532
7533 let observed_cltv_expiry_delta: u32 = p.hops[random_path_index..].iter().map(|h| h.cltv_expiry_delta).sum();
7535
7536 let mut candidates: VecDeque<(NodeId, Vec<u32>)> = VecDeque::new();
7538 candidates.push_back((observation_point, vec![]));
7539
7540 let mut found_plausible_candidate = false;
7541
7542 'candidate_loop: while let Some((cur_node_id, cur_path_cltv_deltas)) = candidates.pop_front() {
7543 if let Some(remaining) = observed_cltv_expiry_delta.checked_sub(cur_path_cltv_deltas.iter().sum::<u32>()) {
7544 if remaining == 0 || remaining.wrapping_rem(40) == 0 || remaining.wrapping_rem(144) == 0 {
7545 found_plausible_candidate = true;
7546 break 'candidate_loop;
7547 }
7548 }
7549
7550 if let Some(cur_node) = network_nodes.get(&cur_node_id) {
7551 for channel_id in &cur_node.channels {
7552 if let Some(channel_info) = network_channels.get(&channel_id) {
7553 if let Some((dir_info, next_id)) = channel_info.as_directed_from(&cur_node_id) {
7554 let next_cltv_expiry_delta = dir_info.direction().cltv_expiry_delta as u32;
7555 if cur_path_cltv_deltas.iter().sum::<u32>()
7556 .saturating_add(next_cltv_expiry_delta) <= observed_cltv_expiry_delta {
7557 let mut new_path_cltv_deltas = cur_path_cltv_deltas.clone();
7558 new_path_cltv_deltas.push(next_cltv_expiry_delta);
7559 candidates.push_back((*next_id, new_path_cltv_deltas));
7560 }
7561 }
7562 }
7563 }
7564 }
7565 }
7566
7567 path_plausibility.push(found_plausible_candidate);
7568 }
7569 assert!(path_plausibility.iter().all(|x| *x));
7570 }
7571
7572 #[test]
7573 #[rustfmt::skip]
7574 fn builds_correct_path_from_hops() {
7575 let (secp_ctx, network, _, _, logger) = build_graph();
7576 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7577 let network_graph = network.read_only();
7578
7579 let random_seed_bytes = [42; 32];
7580 let payment_params = PaymentParameters::from_node_id(nodes[3], 0);
7581 let hops = [nodes[1], nodes[2], nodes[4], nodes[3]];
7582 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
7583 let route = build_route_from_hops_internal(&our_id, &hops, &route_params, &network_graph,
7584 Arc::clone(&logger), &random_seed_bytes).unwrap();
7585 let route_hop_pubkeys = route.paths[0].hops.iter().map(|hop| hop.pubkey).collect::<Vec<_>>();
7586 assert_eq!(hops.len(), route.paths[0].hops.len());
7587 for (idx, hop_pubkey) in hops.iter().enumerate() {
7588 assert!(*hop_pubkey == route_hop_pubkeys[idx]);
7589 }
7590 }
7591
7592 #[test]
7593 #[rustfmt::skip]
7594 fn avoids_saturating_channels() {
7595 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
7596 let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
7597 let decay_params = ProbabilisticScoringDecayParameters::default();
7598 let scorer = ProbabilisticScorer::new(decay_params, &*network_graph, Arc::clone(&logger));
7599
7600 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
7603 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
7604 short_channel_id: 4,
7605 timestamp: 2,
7606 message_flags: 1, channel_flags: 0,
7608 cltv_expiry_delta: (4 << 4) | 1,
7609 htlc_minimum_msat: 0,
7610 htlc_maximum_msat: 250_000_000,
7611 fee_base_msat: 0,
7612 fee_proportional_millionths: 0,
7613 excess_data: Vec::new()
7614 });
7615 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
7616 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
7617 short_channel_id: 13,
7618 timestamp: 2,
7619 message_flags: 1, channel_flags: 0,
7621 cltv_expiry_delta: (13 << 4) | 1,
7622 htlc_minimum_msat: 0,
7623 htlc_maximum_msat: 250_000_000,
7624 fee_base_msat: 0,
7625 fee_proportional_millionths: 0,
7626 excess_data: Vec::new()
7627 });
7628
7629 let config = UserConfig::default();
7630 let payment_params = PaymentParameters::from_node_id(nodes[2], 42)
7631 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
7632 .unwrap();
7633 let random_seed_bytes = [42; 32];
7634
7635 let route_params = RouteParameters::from_payment_params_and_value(
7640 payment_params, 75_000_000);
7641 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
7642 Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes).unwrap();
7643 assert_eq!(route.paths.len(), 2);
7644 assert!((route.paths[0].hops[1].short_channel_id == 4 && route.paths[1].hops[1].short_channel_id == 13) ||
7645 (route.paths[1].hops[1].short_channel_id == 4 && route.paths[0].hops[1].short_channel_id == 13));
7646 }
7647
7648 pub(super) fn random_init_seed() -> u64 {
7649 use core::hash::{BuildHasher, Hasher};
7651 let seed = std::collections::hash_map::RandomState::new().build_hasher().finish();
7652 println!("Using seed of {}", seed);
7653 seed
7654 }
7655
7656 #[test]
7657 #[rustfmt::skip]
7658 fn generate_routes() {
7659 use crate::routing::scoring::ProbabilisticScoringFeeParameters;
7660
7661 let logger = ln_test_utils::TestLogger::new();
7662 let (graph, mut scorer) = match super::bench_utils::read_graph_scorer(&logger) {
7663 Ok(res) => res,
7664 Err(e) => {
7665 eprintln!("{}", e);
7666 return;
7667 },
7668 };
7669
7670 let params = ProbabilisticScoringFeeParameters::default();
7671 let features = super::Bolt11InvoiceFeatures::empty();
7672
7673 super::bench_utils::generate_test_routes(&graph, &mut scorer, ¶ms, features, random_init_seed(), 0, 2);
7674 }
7675
7676 #[test]
7677 #[rustfmt::skip]
7678 fn generate_routes_mpp() {
7679 use crate::routing::scoring::ProbabilisticScoringFeeParameters;
7680
7681 let logger = ln_test_utils::TestLogger::new();
7682 let (graph, mut scorer) = match super::bench_utils::read_graph_scorer(&logger) {
7683 Ok(res) => res,
7684 Err(e) => {
7685 eprintln!("{}", e);
7686 return;
7687 },
7688 };
7689
7690 let params = ProbabilisticScoringFeeParameters::default();
7691 let features = channelmanager::provided_bolt11_invoice_features(&UserConfig::default());
7692
7693 super::bench_utils::generate_test_routes(&graph, &mut scorer, ¶ms, features, random_init_seed(), 0, 2);
7694 }
7695
7696 #[test]
7697 #[rustfmt::skip]
7698 fn generate_large_mpp_routes() {
7699 use crate::routing::scoring::ProbabilisticScoringFeeParameters;
7700
7701 let logger = ln_test_utils::TestLogger::new();
7702 let (graph, mut scorer) = match super::bench_utils::read_graph_scorer(&logger) {
7703 Ok(res) => res,
7704 Err(e) => {
7705 eprintln!("{}", e);
7706 return;
7707 },
7708 };
7709
7710 let params = ProbabilisticScoringFeeParameters::default();
7711 let features = channelmanager::provided_bolt11_invoice_features(&UserConfig::default());
7712
7713 super::bench_utils::generate_test_routes(&graph, &mut scorer, ¶ms, features, random_init_seed(), 1_000_000, 2);
7714 }
7715
7716 #[test]
7717 #[rustfmt::skip]
7718 fn honors_manual_penalties() {
7719 let (secp_ctx, network_graph, _, _, logger) = build_line_graph();
7720 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7721
7722 let random_seed_bytes = [42; 32];
7723 let mut scorer_params = ProbabilisticScoringFeeParameters::default();
7724 let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), Arc::clone(&network_graph), Arc::clone(&logger));
7725
7726 let usage = ChannelUsage {
7728 amount_msat: 0,
7729 inflight_htlc_msat: 0,
7730 effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_000 },
7731 };
7732 scorer_params.set_manual_penalty(&NodeId::from_pubkey(&nodes[3]), 123);
7733 scorer_params.set_manual_penalty(&NodeId::from_pubkey(&nodes[4]), 456);
7734 let network_graph = network_graph.read_only();
7735 let channels = network_graph.channels();
7736 let channel = channels.get(&5).unwrap();
7737 let info = channel.as_directed_from(&NodeId::from_pubkey(&nodes[3])).unwrap();
7738 let candidate: CandidateRouteHop = CandidateRouteHop::PublicHop(PublicHopCandidate {
7739 info: info.0,
7740 short_channel_id: 5,
7741 });
7742 assert_eq!(scorer.channel_penalty_msat(&candidate, usage, &scorer_params), 456);
7743
7744 let payment_params = PaymentParameters::from_node_id(nodes[10], 42);
7746 let route_params = RouteParameters::from_payment_params_and_value(
7747 payment_params, 100);
7748 let route = get_route(&our_id, &route_params, &network_graph, None,
7749 Arc::clone(&logger), &scorer, &scorer_params, &random_seed_bytes);
7750 assert!(route.is_ok());
7751
7752 scorer_params.add_banned(&NodeId::from_pubkey(&nodes[3]));
7754 let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes);
7755 assert!(route.is_err());
7756
7757 scorer_params.remove_banned(&NodeId::from_pubkey(&nodes[3]));
7759 let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes);
7760 assert!(route.is_ok());
7761 }
7762
7763 #[test]
7764 #[rustfmt::skip]
7765 fn abide_by_route_hint_max_htlc() {
7766 let (secp_ctx, network_graph, _, _, logger) = build_graph();
7769 let netgraph = network_graph.read_only();
7770 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7771 let scorer = ln_test_utils::TestScorer::new();
7772 let random_seed_bytes = [42; 32];
7773 let config = UserConfig::default();
7774
7775 let max_htlc_msat = 50_000;
7776 let route_hint_1 = RouteHint(vec![RouteHintHop {
7777 src_node_id: nodes[2],
7778 short_channel_id: 42,
7779 fees: RoutingFees {
7780 base_msat: 100,
7781 proportional_millionths: 0,
7782 },
7783 cltv_expiry_delta: 10,
7784 htlc_minimum_msat: None,
7785 htlc_maximum_msat: Some(max_htlc_msat),
7786 }]);
7787 let dest_node_id = ln_test_utils::pubkey(42);
7788 let payment_params = PaymentParameters::from_node_id(dest_node_id, 42)
7789 .with_route_hints(vec![route_hint_1.clone()]).unwrap()
7790 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
7791 .unwrap();
7792
7793 let mut route_params = RouteParameters::from_payment_params_and_value(
7796 payment_params, max_htlc_msat + 1);
7797 route_params.max_total_routing_fee_msat = None;
7798 if let Err(err) = get_route(&our_id,
7799 &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(),
7800 &random_seed_bytes)
7801 {
7802 assert_eq!(err, "Failed to find a sufficient route to the given destination");
7803 } else { panic!(); }
7804
7805 let mut route_hint_2 = route_hint_1.clone();
7807 route_hint_2.0[0].short_channel_id = 43;
7808 let payment_params = PaymentParameters::from_node_id(dest_node_id, 42)
7809 .with_route_hints(vec![route_hint_1, route_hint_2]).unwrap()
7810 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
7811 .unwrap();
7812 let mut route_params = RouteParameters::from_payment_params_and_value(
7813 payment_params, max_htlc_msat + 1);
7814 route_params.max_total_routing_fee_msat = Some(max_htlc_msat * 2);
7815 let route = get_route(&our_id, &route_params, &netgraph, None, Arc::clone(&logger),
7816 &scorer, &Default::default(), &random_seed_bytes).unwrap();
7817 assert_eq!(route.paths.len(), 2);
7818 assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat);
7819 assert!(route.paths[1].hops.last().unwrap().fee_msat <= max_htlc_msat);
7820 }
7821
7822 #[test]
7823 #[rustfmt::skip]
7824 fn direct_channel_to_hints_with_max_htlc() {
7825 let logger = Arc::new(ln_test_utils::TestLogger::new());
7828 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
7829 let scorer = ln_test_utils::TestScorer::new();
7830 let random_seed_bytes = [42; 32];
7831 let config = UserConfig::default();
7832
7833 let our_node_id = ln_test_utils::pubkey(42);
7834 let intermed_node_id = ln_test_utils::pubkey(43);
7835 let first_hop = [get_channel_details(Some(42), intermed_node_id, InitFeatures::from_le_bytes(vec![0b11]), 10_000_000)];
7836
7837 let amt_msat = 900_000;
7838 let max_htlc_msat = 500_000;
7839 let route_hint_1 = RouteHint(vec![RouteHintHop {
7840 src_node_id: intermed_node_id,
7841 short_channel_id: 44,
7842 fees: RoutingFees {
7843 base_msat: 100,
7844 proportional_millionths: 0,
7845 },
7846 cltv_expiry_delta: 10,
7847 htlc_minimum_msat: None,
7848 htlc_maximum_msat: Some(max_htlc_msat),
7849 }, RouteHintHop {
7850 src_node_id: intermed_node_id,
7851 short_channel_id: 45,
7852 fees: RoutingFees {
7853 base_msat: 100,
7854 proportional_millionths: 0,
7855 },
7856 cltv_expiry_delta: 10,
7857 htlc_minimum_msat: None,
7858 htlc_maximum_msat: Some(max_htlc_msat - 50),
7860 }]);
7861 let mut route_hint_2 = route_hint_1.clone();
7862 route_hint_2.0[0].short_channel_id = 46;
7863 route_hint_2.0[1].short_channel_id = 47;
7864 let dest_node_id = ln_test_utils::pubkey(44);
7865 let payment_params = PaymentParameters::from_node_id(dest_node_id, 42)
7866 .with_route_hints(vec![route_hint_1, route_hint_2]).unwrap()
7867 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
7868 .unwrap();
7869
7870 let route_params = RouteParameters::from_payment_params_and_value(
7871 payment_params, amt_msat);
7872 let route = get_route(&our_node_id, &route_params, &network_graph.read_only(),
7873 Some(&first_hop.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
7874 &Default::default(), &random_seed_bytes).unwrap();
7875 assert_eq!(route.paths.len(), 2);
7876 assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat);
7877 assert!(route.paths[1].hops.last().unwrap().fee_msat <= max_htlc_msat);
7878 assert_eq!(route.get_total_amount(), amt_msat);
7879
7880 let first_hops = [
7883 get_channel_details(Some(42), intermed_node_id, InitFeatures::from_le_bytes(vec![0b11]), amt_msat - 10),
7884 get_channel_details(Some(43), intermed_node_id, InitFeatures::from_le_bytes(vec![0b11]), amt_msat - 10),
7885 ];
7886 let route = get_route(&our_node_id, &route_params, &network_graph.read_only(),
7887 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
7888 &Default::default(), &random_seed_bytes).unwrap();
7889 assert_eq!(route.paths.len(), 2);
7890 assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat);
7891 assert!(route.paths[1].hops.last().unwrap().fee_msat <= max_htlc_msat);
7892 assert_eq!(route.get_total_amount(), amt_msat);
7893
7894 let blinded_payinfo = BlindedPayInfo {
7896 fee_base_msat: 100,
7897 fee_proportional_millionths: 0,
7898 htlc_minimum_msat: 1,
7899 htlc_maximum_msat: max_htlc_msat,
7900 cltv_expiry_delta: 10,
7901 features: BlindedHopFeatures::empty(),
7902 };
7903 let blinded_path = dummy_blinded_path(intermed_node_id, blinded_payinfo);
7904 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
7905 let payment_params = PaymentParameters::blinded(vec![
7906 blinded_path.clone(), blinded_path.clone()
7907 ]).with_bolt12_features(bolt12_features).unwrap();
7908 let route_params = RouteParameters::from_payment_params_and_value(
7909 payment_params, amt_msat);
7910 let route = get_route(&our_node_id, &route_params, &network_graph.read_only(),
7911 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
7912 &Default::default(), &random_seed_bytes).unwrap();
7913 assert_eq!(route.paths.len(), 2);
7914 assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat);
7915 assert!(route.paths[1].hops.last().unwrap().fee_msat <= max_htlc_msat);
7916 assert_eq!(route.get_total_amount(), amt_msat);
7917 }
7918
7919 #[test]
7920 #[rustfmt::skip]
7921 fn blinded_route_ser() {
7922 let mut route = Route { paths: vec![Path {
7924 hops: vec![RouteHop {
7925 pubkey: ln_test_utils::pubkey(50),
7926 node_features: NodeFeatures::empty(),
7927 short_channel_id: 42,
7928 channel_features: ChannelFeatures::empty(),
7929 fee_msat: 100,
7930 cltv_expiry_delta: 0,
7931 maybe_announced_channel: true,
7932 }],
7933 blinded_tail: Some(BlindedTail {
7934 trampoline_hops: vec![],
7935 hops: vec![
7936 BlindedHop { blinded_node_id: ln_test_utils::pubkey(44), encrypted_payload: Vec::new() },
7937 BlindedHop { blinded_node_id: ln_test_utils::pubkey(45), encrypted_payload: Vec::new() }
7938 ],
7939 blinding_point: ln_test_utils::pubkey(43),
7940 excess_final_cltv_expiry_delta: 40,
7941 final_value_msat: 100,
7942 })}, Path {
7943 hops: vec![RouteHop {
7944 pubkey: ln_test_utils::pubkey(51),
7945 node_features: NodeFeatures::empty(),
7946 short_channel_id: 43,
7947 channel_features: ChannelFeatures::empty(),
7948 fee_msat: 100,
7949 cltv_expiry_delta: 0,
7950 maybe_announced_channel: true,
7951 }], blinded_tail: None }],
7952 route_params: None,
7953 };
7954 let encoded_route = route.encode();
7955 let decoded_route: Route = Readable::read(&mut Cursor::new(&encoded_route[..])).unwrap();
7956 assert_eq!(decoded_route.paths[0].blinded_tail, route.paths[0].blinded_tail);
7957 assert_eq!(decoded_route.paths[1].blinded_tail, route.paths[1].blinded_tail);
7958
7959 route.paths[1].blinded_tail = Some(BlindedTail {
7961 trampoline_hops: vec![],
7962 hops: vec![
7963 BlindedHop { blinded_node_id: ln_test_utils::pubkey(48), encrypted_payload: Vec::new() },
7964 BlindedHop { blinded_node_id: ln_test_utils::pubkey(49), encrypted_payload: Vec::new() }
7965 ],
7966 blinding_point: ln_test_utils::pubkey(47),
7967 excess_final_cltv_expiry_delta: 41,
7968 final_value_msat: 101,
7969 });
7970 let encoded_route = route.encode();
7971 let decoded_route: Route = Readable::read(&mut Cursor::new(&encoded_route[..])).unwrap();
7972 assert_eq!(decoded_route.paths[0].blinded_tail, route.paths[0].blinded_tail);
7973 assert_eq!(decoded_route.paths[1].blinded_tail, route.paths[1].blinded_tail);
7974 }
7975
7976 #[test]
7977 #[rustfmt::skip]
7978 fn blinded_path_inflight_processing() {
7979 let mut inflight_htlcs = InFlightHtlcs::new();
7982 let path = Path {
7983 hops: vec![RouteHop {
7984 pubkey: ln_test_utils::pubkey(42),
7985 node_features: NodeFeatures::empty(),
7986 short_channel_id: 42,
7987 channel_features: ChannelFeatures::empty(),
7988 fee_msat: 100,
7989 cltv_expiry_delta: 0,
7990 maybe_announced_channel: false,
7991 },
7992 RouteHop {
7993 pubkey: ln_test_utils::pubkey(43),
7994 node_features: NodeFeatures::empty(),
7995 short_channel_id: 43,
7996 channel_features: ChannelFeatures::empty(),
7997 fee_msat: 1,
7998 cltv_expiry_delta: 0,
7999 maybe_announced_channel: false,
8000 }],
8001 blinded_tail: Some(BlindedTail {
8002 trampoline_hops: vec![],
8003 hops: vec![BlindedHop { blinded_node_id: ln_test_utils::pubkey(49), encrypted_payload: Vec::new() }],
8004 blinding_point: ln_test_utils::pubkey(48),
8005 excess_final_cltv_expiry_delta: 0,
8006 final_value_msat: 200,
8007 }),
8008 };
8009 inflight_htlcs.process_path(&path, ln_test_utils::pubkey(44));
8010 assert_eq!(*inflight_htlcs.0.get(&(42, true)).unwrap(), 301);
8011 assert_eq!(*inflight_htlcs.0.get(&(43, false)).unwrap(), 201);
8012 }
8013
8014 #[test]
8015 #[rustfmt::skip]
8016 fn blinded_path_cltv_shadow_offset() {
8017 let mut route = Route { paths: vec![Path {
8019 hops: vec![RouteHop {
8020 pubkey: ln_test_utils::pubkey(42),
8021 node_features: NodeFeatures::empty(),
8022 short_channel_id: 42,
8023 channel_features: ChannelFeatures::empty(),
8024 fee_msat: 100,
8025 cltv_expiry_delta: 0,
8026 maybe_announced_channel: false,
8027 },
8028 RouteHop {
8029 pubkey: ln_test_utils::pubkey(43),
8030 node_features: NodeFeatures::empty(),
8031 short_channel_id: 43,
8032 channel_features: ChannelFeatures::empty(),
8033 fee_msat: 1,
8034 cltv_expiry_delta: 0,
8035 maybe_announced_channel: false,
8036 }
8037 ],
8038 blinded_tail: Some(BlindedTail {
8039 trampoline_hops: vec![],
8040 hops: vec![
8041 BlindedHop { blinded_node_id: ln_test_utils::pubkey(45), encrypted_payload: Vec::new() },
8042 BlindedHop { blinded_node_id: ln_test_utils::pubkey(46), encrypted_payload: Vec::new() }
8043 ],
8044 blinding_point: ln_test_utils::pubkey(44),
8045 excess_final_cltv_expiry_delta: 0,
8046 final_value_msat: 200,
8047 }),
8048 }], route_params: None};
8049
8050 let payment_params = PaymentParameters::from_node_id(ln_test_utils::pubkey(47), 18);
8051 let (_, network_graph, _, _, _) = build_line_graph();
8052 add_random_cltv_offset(&mut route, &payment_params, &network_graph.read_only(), &[0; 32]);
8053 assert_eq!(route.paths[0].blinded_tail.as_ref().unwrap().excess_final_cltv_expiry_delta, 40);
8054 assert_eq!(route.paths[0].hops.last().unwrap().cltv_expiry_delta, 40);
8055 }
8056
8057 #[test]
8058 fn simple_blinded_route_hints() {
8059 do_simple_blinded_route_hints(1);
8060 do_simple_blinded_route_hints(2);
8061 do_simple_blinded_route_hints(3);
8062 }
8063
8064 #[rustfmt::skip]
8065 fn do_simple_blinded_route_hints(num_blinded_hops: usize) {
8066 let (secp_ctx, network, _, _, logger) = build_graph();
8068 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8069 let network_graph = network.read_only();
8070
8071 let scorer = ln_test_utils::TestScorer::new();
8072 let random_seed_bytes = [42; 32];
8073
8074 let mut blinded_hops = Vec::new();
8075 for i in 0..num_blinded_hops {
8076 blinded_hops.push(
8077 BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 + i as u8), encrypted_payload: Vec::new() },
8078 );
8079 }
8080 let blinded_payinfo = BlindedPayInfo {
8081 fee_base_msat: 100,
8082 fee_proportional_millionths: 500,
8083 htlc_minimum_msat: 1000,
8084 htlc_maximum_msat: 100_000_000,
8085 cltv_expiry_delta: 15,
8086 features: BlindedHopFeatures::empty(),
8087 };
8088 let blinded_path = BlindedPaymentPath::from_blinded_path_and_payinfo(
8089 nodes[2], ln_test_utils::pubkey(42), blinded_hops, blinded_payinfo.clone()
8090 );
8091 let payment_params = PaymentParameters::blinded(vec![blinded_path.clone(), blinded_path.clone()]);
8092
8093 let encoded_params = payment_params.encode();
8095 let mut s = Cursor::new(&encoded_params);
8096 let mut reader = FixedLengthReader::new(&mut s, encoded_params.len() as u64);
8097 let decoded_params: PaymentParameters = ReadableArgs::read(&mut reader, 42).unwrap();
8098 assert_eq!(payment_params, decoded_params);
8099
8100 let route_params = RouteParameters::from_payment_params_and_value(
8101 payment_params, 1001);
8102 let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
8103 &scorer, &Default::default(), &random_seed_bytes).unwrap();
8104 assert_eq!(route.paths.len(), 1);
8105 assert_eq!(route.paths[0].hops.len(), 2);
8106
8107 let tail = route.paths[0].blinded_tail.as_ref().unwrap();
8108 assert_eq!(&tail.hops, blinded_path.blinded_hops());
8109 assert_eq!(tail.excess_final_cltv_expiry_delta, 0);
8110 assert_eq!(tail.final_value_msat, 1001);
8111
8112 let final_hop = route.paths[0].hops.last().unwrap();
8113 assert_eq!(
8114 NodeId::from_pubkey(&final_hop.pubkey),
8115 *blinded_path.public_introduction_node_id(&network_graph).unwrap()
8116 );
8117 if tail.hops.len() > 1 {
8118 assert_eq!(final_hop.fee_msat,
8119 blinded_payinfo.fee_base_msat as u64 + blinded_payinfo.fee_proportional_millionths as u64 * tail.final_value_msat / 1000000);
8120 assert_eq!(final_hop.cltv_expiry_delta, blinded_payinfo.cltv_expiry_delta as u32);
8121 } else {
8122 assert_eq!(final_hop.fee_msat, 0);
8123 assert_eq!(final_hop.cltv_expiry_delta, 0);
8124 }
8125 }
8126
8127 #[test]
8128 #[rustfmt::skip]
8129 fn blinded_path_routing_errors() {
8130 let (secp_ctx, network, _, _, logger) = build_graph();
8132 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8133 let network_graph = network.read_only();
8134
8135 let scorer = ln_test_utils::TestScorer::new();
8136 let random_seed_bytes = [42; 32];
8137
8138 let blinded_payinfo = BlindedPayInfo {
8139 fee_base_msat: 100,
8140 fee_proportional_millionths: 500,
8141 htlc_minimum_msat: 1000,
8142 htlc_maximum_msat: 100_000_000,
8143 cltv_expiry_delta: 15,
8144 features: BlindedHopFeatures::empty(),
8145 };
8146
8147 let invalid_blinded_path_2 = dummy_one_hop_blinded_path(nodes[2], blinded_payinfo.clone());
8148 let invalid_blinded_path_3 = dummy_one_hop_blinded_path(nodes[3], blinded_payinfo.clone());
8149 let payment_params = PaymentParameters::blinded(vec![
8150 invalid_blinded_path_2, invalid_blinded_path_3]);
8151 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001);
8152 match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
8153 &scorer, &Default::default(), &random_seed_bytes)
8154 {
8155 Err(err) => {
8156 assert_eq!(err, "1-hop blinded paths must all have matching introduction node ids");
8157 },
8158 _ => panic!("Expected error")
8159 }
8160
8161 let invalid_blinded_path = dummy_blinded_path(our_id, blinded_payinfo.clone());
8162 let payment_params = PaymentParameters::blinded(vec![invalid_blinded_path]);
8163 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001);
8164 match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
8165 &Default::default(), &random_seed_bytes)
8166 {
8167 Err(err) => {
8168 assert_eq!(err, "Cannot generate a route to blinded paths if we are the introduction node to all of them");
8169 },
8170 _ => panic!("Expected error")
8171 }
8172
8173 let mut invalid_blinded_path = dummy_one_hop_blinded_path(ln_test_utils::pubkey(46), blinded_payinfo);
8174 invalid_blinded_path.clear_blinded_hops();
8175 let payment_params = PaymentParameters::blinded(vec![invalid_blinded_path]);
8176 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001);
8177 match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
8178 &Default::default(), &random_seed_bytes)
8179 {
8180 Err(err) => {
8181 assert_eq!(err, "0-hop blinded path provided");
8182 },
8183 _ => panic!("Expected error")
8184 }
8185 }
8186
8187 #[test]
8188 #[rustfmt::skip]
8189 fn matching_intro_node_paths_provided() {
8190 let (secp_ctx, network, _, _, logger) = build_graph();
8193 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8194 let network_graph = network.read_only();
8195
8196 let scorer = ln_test_utils::TestScorer::new();
8197 let random_seed_bytes = [42; 32];
8198 let config = UserConfig::default();
8199
8200 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8201 let blinded_payinfo_1 = BlindedPayInfo {
8202 fee_base_msat: 0,
8203 fee_proportional_millionths: 0,
8204 htlc_minimum_msat: 0,
8205 htlc_maximum_msat: 30_000,
8206 cltv_expiry_delta: 0,
8207 features: BlindedHopFeatures::empty(),
8208 };
8209 let blinded_path_1 = dummy_blinded_path(nodes[2], blinded_payinfo_1.clone());
8210
8211 let mut blinded_payinfo_2 = blinded_payinfo_1;
8212 blinded_payinfo_2.htlc_maximum_msat = 70_000;
8213 let blinded_path_2 = BlindedPaymentPath::from_blinded_path_and_payinfo(
8214 nodes[2],
8215 ln_test_utils::pubkey(43),
8216 vec![
8217 BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() },
8218 BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() }
8219 ],
8220 blinded_payinfo_2
8221 );
8222
8223 let blinded_hints = vec![blinded_path_1.clone(), blinded_path_2.clone()];
8224 let payment_params = PaymentParameters::blinded(blinded_hints.clone())
8225 .with_bolt12_features(bolt12_features).unwrap();
8226
8227 let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100_000);
8228 route_params.max_total_routing_fee_msat = Some(100_000);
8229 let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
8230 &scorer, &Default::default(), &random_seed_bytes).unwrap();
8231 assert_eq!(route.paths.len(), 2);
8232 let mut total_amount_paid_msat = 0;
8233 for path in route.paths.into_iter() {
8234 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
8235 if let Some(bt) = &path.blinded_tail {
8236 assert_eq!(bt.blinding_point,
8237 blinded_hints.iter().find(|p| p.payinfo.htlc_maximum_msat == path.final_value_msat())
8238 .map(|bp| bp.blinding_point()).unwrap());
8239 } else { panic!(); }
8240 total_amount_paid_msat += path.final_value_msat();
8241 }
8242 assert_eq!(total_amount_paid_msat, 100_000);
8243 }
8244
8245 #[test]
8246 #[rustfmt::skip]
8247 fn direct_to_intro_node() {
8248 let secp_ctx = Secp256k1::new();
8258 let logger = Arc::new(ln_test_utils::TestLogger::new());
8259 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8260 let gossip_sync = P2PGossipSync::new(Arc::clone(&network_graph), None, Arc::clone(&logger));
8261 let scorer = ln_test_utils::TestScorer::new();
8262 let random_seed_bytes = [42; 32];
8263
8264 let amt_msat = 10_000_000;
8265 let (_, _, privkeys, nodes) = get_nodes(&secp_ctx);
8266 add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[1],
8267 ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1);
8268 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
8269 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8270 short_channel_id: 1,
8271 timestamp: 1,
8272 message_flags: 1, channel_flags: 0,
8274 cltv_expiry_delta: 42,
8275 htlc_minimum_msat: 1_000,
8276 htlc_maximum_msat: 10_000_000,
8277 fee_base_msat: 800,
8278 fee_proportional_millionths: 0,
8279 excess_data: Vec::new()
8280 });
8281 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
8282 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8283 short_channel_id: 1,
8284 timestamp: 1,
8285 message_flags: 1, channel_flags: 1,
8287 cltv_expiry_delta: 42,
8288 htlc_minimum_msat: 1_000,
8289 htlc_maximum_msat: 10_000_000,
8290 fee_base_msat: 800,
8291 fee_proportional_millionths: 0,
8292 excess_data: Vec::new()
8293 });
8294 let first_hops = [
8295 get_channel_details(Some(1), nodes[1], InitFeatures::from_le_bytes(vec![0b11]), 10_000_000)
8296 ];
8297
8298 let blinded_payinfo = BlindedPayInfo {
8299 fee_base_msat: 1000,
8300 fee_proportional_millionths: 0,
8301 htlc_minimum_msat: 1000,
8302 htlc_maximum_msat: MAX_VALUE_MSAT,
8303 cltv_expiry_delta: 0,
8304 features: BlindedHopFeatures::empty(),
8305 };
8306 let blinded_path = dummy_blinded_path(nodes[1], blinded_payinfo.clone());
8307 let blinded_hints = vec![blinded_path];
8308
8309 let payment_params = PaymentParameters::blinded(blinded_hints.clone());
8310
8311 let netgraph = network_graph.read_only();
8312 let route_params = RouteParameters::from_payment_params_and_value(
8313 payment_params.clone(), amt_msat);
8314 if let Err(err) = get_route(&nodes[0], &route_params, &netgraph,
8315 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
8316 &Default::default(), &random_seed_bytes) {
8317 assert_eq!(err, "Failed to find a path to the given destination");
8318 } else { panic!("Expected error") }
8319
8320 let amt_minus_blinded_path_fee = amt_msat - blinded_payinfo.fee_base_msat as u64;
8322 let route_params = RouteParameters::from_payment_params_and_value(
8323 payment_params, amt_minus_blinded_path_fee);
8324 let route = get_route(&nodes[0], &route_params, &netgraph,
8325 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
8326 &Default::default(), &random_seed_bytes).unwrap();
8327 assert_eq!(route.get_total_fees(), blinded_payinfo.fee_base_msat as u64);
8328 assert_eq!(route.get_total_amount(), amt_minus_blinded_path_fee);
8329 }
8330
8331 #[test]
8332 #[rustfmt::skip]
8333 fn direct_to_matching_intro_nodes() {
8334 let secp_ctx = Secp256k1::new();
8347 let logger = Arc::new(ln_test_utils::TestLogger::new());
8348 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8349 let scorer = ln_test_utils::TestScorer::new();
8350 let random_seed_bytes = [42; 32];
8351 let config = UserConfig::default();
8352
8353 let amt_msat = 21_7020_5185_1403_2640;
8355 let (_, _, _, nodes) = get_nodes(&secp_ctx);
8356 let first_hops = [
8357 get_channel_details(Some(1), nodes[1], channelmanager::provided_init_features(&config),
8358 18446744073709551615),
8359 ];
8360
8361 let blinded_payinfo = BlindedPayInfo {
8362 fee_base_msat: 5046_2720,
8363 fee_proportional_millionths: 0,
8364 htlc_minimum_msat: 4503_5996_2737_0496,
8365 htlc_maximum_msat: 45_0359_9627_3704_9600,
8366 cltv_expiry_delta: 0,
8367 features: BlindedHopFeatures::empty(),
8368 };
8369 let blinded_path = dummy_blinded_path(nodes[1], blinded_payinfo.clone());
8370 let mut blinded_hints = vec![blinded_path.clone(), blinded_path.clone()];
8371 blinded_hints[1].payinfo.fee_base_msat = 419_4304;
8372 blinded_hints[1].payinfo.fee_proportional_millionths = 257;
8373 blinded_hints[1].payinfo.htlc_minimum_msat = 280_8908_6115_8400;
8374 blinded_hints[1].payinfo.htlc_maximum_msat = 2_8089_0861_1584_0000;
8375 blinded_hints[1].payinfo.cltv_expiry_delta = 0;
8376
8377 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8378 let payment_params = PaymentParameters::blinded(blinded_hints.clone())
8379 .with_bolt12_features(bolt12_features).unwrap();
8380
8381 let netgraph = network_graph.read_only();
8382 let route_params = RouteParameters::from_payment_params_and_value(
8383 payment_params, amt_msat);
8384 let route = get_route(&nodes[0], &route_params, &netgraph,
8385 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
8386 &Default::default(), &random_seed_bytes).unwrap();
8387 assert_eq!(route.get_total_fees(), blinded_payinfo.fee_base_msat as u64);
8388 assert_eq!(route.get_total_amount(), amt_msat);
8389 }
8390
8391 #[test]
8392 #[rustfmt::skip]
8393 fn we_are_intro_node_candidate_hops() {
8394 let (secp_ctx, network_graph, _, _, logger) = build_graph();
8399 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8400 let scorer = ln_test_utils::TestScorer::new();
8401 let random_seed_bytes = [42; 32];
8402 let config = UserConfig::default();
8403
8404 let amt_msat = 21_7020_5185_1423_0019;
8406
8407 let blinded_payinfo = BlindedPayInfo {
8408 fee_base_msat: 5052_9027,
8409 fee_proportional_millionths: 0,
8410 htlc_minimum_msat: 21_7020_5185_1423_0019,
8411 htlc_maximum_msat: 1844_6744_0737_0955_1615,
8412 cltv_expiry_delta: 0,
8413 features: BlindedHopFeatures::empty(),
8414 };
8415 let blinded_path = dummy_blinded_path(our_id, blinded_payinfo.clone());
8416 let mut blinded_hints = vec![blinded_path.clone(), blinded_path.clone()];
8417 blinded_hints[1] = dummy_blinded_path(nodes[6], blinded_payinfo);
8418
8419 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8420 let payment_params = PaymentParameters::blinded(blinded_hints.clone())
8421 .with_bolt12_features(bolt12_features.clone()).unwrap();
8422
8423 let netgraph = network_graph.read_only();
8424 let route_params = RouteParameters::from_payment_params_and_value(
8425 payment_params, amt_msat);
8426 if let Err(err) = get_route(
8427 &our_id, &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes
8428 ) {
8429 assert_eq!(err, "Failed to find a path to the given destination");
8430 } else { panic!() }
8431 }
8432
8433 #[test]
8434 #[rustfmt::skip]
8435 fn we_are_intro_node_bp_in_final_path_fee_calc() {
8436 let (secp_ctx, network_graph, _, _, logger) = build_graph();
8441 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8442 let scorer = ln_test_utils::TestScorer::new();
8443 let random_seed_bytes = [42; 32];
8444 let config = UserConfig::default();
8445
8446 let amt_msat = 21_7020_5185_1423_0019;
8448
8449 let blinded_payinfo = BlindedPayInfo {
8450 fee_base_msat: 10_4425_1395,
8451 fee_proportional_millionths: 0,
8452 htlc_minimum_msat: 21_7301_9934_9094_0931,
8453 htlc_maximum_msat: 1844_6744_0737_0955_1615,
8454 cltv_expiry_delta: 0,
8455 features: BlindedHopFeatures::empty(),
8456 };
8457 let blinded_path = dummy_blinded_path(our_id, blinded_payinfo.clone());
8458 let mut blinded_hints = vec![
8459 blinded_path.clone(), blinded_path.clone(), blinded_path.clone(),
8460 ];
8461 blinded_hints[1].payinfo.fee_base_msat = 5052_9027;
8462 blinded_hints[1].payinfo.htlc_minimum_msat = 21_7020_5185_1423_0019;
8463 blinded_hints[1].payinfo.htlc_maximum_msat = 1844_6744_0737_0955_1615;
8464
8465 blinded_hints[2] = dummy_blinded_path(nodes[6], blinded_payinfo);
8466
8467 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8468 let payment_params = PaymentParameters::blinded(blinded_hints.clone())
8469 .with_bolt12_features(bolt12_features.clone()).unwrap();
8470
8471 let netgraph = network_graph.read_only();
8472 let route_params = RouteParameters::from_payment_params_and_value(
8473 payment_params, amt_msat);
8474 if let Err(err) = get_route(
8475 &our_id, &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes
8476 ) {
8477 assert_eq!(err, "Failed to find a path to the given destination");
8478 } else { panic!() }
8479 }
8480
8481 #[test]
8482 fn min_htlc_overpay_violates_max_htlc() {
8483 do_min_htlc_overpay_violates_max_htlc(true);
8484 do_min_htlc_overpay_violates_max_htlc(false);
8485 }
8486 #[rustfmt::skip]
8487 fn do_min_htlc_overpay_violates_max_htlc(blinded_payee: bool) {
8488 let secp_ctx = Secp256k1::new();
8493 let logger = Arc::new(ln_test_utils::TestLogger::new());
8494 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8495 let scorer = ln_test_utils::TestScorer::new();
8496 let random_seed_bytes = [42; 32];
8497 let config = UserConfig::default();
8498
8499 let amt_msat = 7_4009_8048;
8501 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8502 let first_hop_outbound_capacity = 2_7345_2000;
8503 let first_hops = [get_channel_details(
8504 Some(200), nodes[0], channelmanager::provided_init_features(&config),
8505 first_hop_outbound_capacity
8506 )];
8507
8508 let base_fee = 1_6778_3453;
8509 let htlc_min = 2_5165_8240;
8510 let payment_params = if blinded_payee {
8511 let blinded_payinfo = BlindedPayInfo {
8512 fee_base_msat: base_fee,
8513 fee_proportional_millionths: 0,
8514 htlc_minimum_msat: htlc_min,
8515 htlc_maximum_msat: htlc_min * 1000,
8516 cltv_expiry_delta: 0,
8517 features: BlindedHopFeatures::empty(),
8518 };
8519 let blinded_path = dummy_blinded_path(nodes[0], blinded_payinfo);
8520 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8521 PaymentParameters::blinded(vec![blinded_path])
8522 .with_bolt12_features(bolt12_features.clone()).unwrap()
8523 } else {
8524 let route_hint = RouteHint(vec![RouteHintHop {
8525 src_node_id: nodes[0],
8526 short_channel_id: 42,
8527 fees: RoutingFees {
8528 base_msat: base_fee,
8529 proportional_millionths: 0,
8530 },
8531 cltv_expiry_delta: 10,
8532 htlc_minimum_msat: Some(htlc_min),
8533 htlc_maximum_msat: None,
8534 }]);
8535
8536 PaymentParameters::from_node_id(nodes[1], 42)
8537 .with_route_hints(vec![route_hint]).unwrap()
8538 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap()
8539 };
8540
8541 let netgraph = network_graph.read_only();
8542 let route_params = RouteParameters::from_payment_params_and_value(
8543 payment_params, amt_msat);
8544 if let Err(err) = get_route(
8545 &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::<Vec<_>>()),
8546 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes
8547 ) {
8548 assert_eq!(err, "Failed to find a path to the given destination");
8549 } else { panic!() }
8550 }
8551
8552 #[test]
8553 #[rustfmt::skip]
8554 fn previously_used_liquidity_violates_max_htlc() {
8555 do_previously_used_liquidity_violates_max_htlc(true);
8556 do_previously_used_liquidity_violates_max_htlc(false);
8557
8558 }
8559 #[rustfmt::skip]
8560 fn do_previously_used_liquidity_violates_max_htlc(blinded_payee: bool) {
8561 let secp_ctx = Secp256k1::new();
8567 let logger = Arc::new(ln_test_utils::TestLogger::new());
8568 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8569 let scorer = ln_test_utils::TestScorer::new();
8570 let random_seed_bytes = [42; 32];
8571 let config = UserConfig::default();
8572
8573 let amt_msat = 52_4288;
8575 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8576 let first_hops = [get_channel_details(
8577 Some(161), nodes[0], channelmanager::provided_init_features(&config), 486_4000
8578 ), get_channel_details(
8579 Some(122), nodes[0], channelmanager::provided_init_features(&config), 179_5000
8580 )];
8581
8582 let base_fees = [0, 425_9840, 0, 0];
8583 let htlc_mins = [1_4392, 19_7401, 1027, 6_5535];
8584 let payment_params = if blinded_payee {
8585 let mut blinded_hints = Vec::new();
8586 for (base_fee, htlc_min) in base_fees.iter().zip(htlc_mins.iter()) {
8587 let blinded_payinfo = BlindedPayInfo {
8588 fee_base_msat: *base_fee,
8589 fee_proportional_millionths: 0,
8590 htlc_minimum_msat: *htlc_min,
8591 htlc_maximum_msat: htlc_min * 100,
8592 cltv_expiry_delta: 10,
8593 features: BlindedHopFeatures::empty(),
8594 };
8595 blinded_hints.push(dummy_blinded_path(nodes[0], blinded_payinfo));
8596 }
8597 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8598 PaymentParameters::blinded(blinded_hints.clone())
8599 .with_bolt12_features(bolt12_features.clone()).unwrap()
8600 } else {
8601 let mut route_hints = Vec::new();
8602 for (idx, (base_fee, htlc_min)) in base_fees.iter().zip(htlc_mins.iter()).enumerate() {
8603 route_hints.push(RouteHint(vec![RouteHintHop {
8604 src_node_id: nodes[0],
8605 short_channel_id: 42 + idx as u64,
8606 fees: RoutingFees {
8607 base_msat: *base_fee,
8608 proportional_millionths: 0,
8609 },
8610 cltv_expiry_delta: 10,
8611 htlc_minimum_msat: Some(*htlc_min),
8612 htlc_maximum_msat: Some(htlc_min * 100),
8613 }]));
8614 }
8615 PaymentParameters::from_node_id(nodes[1], 42)
8616 .with_route_hints(route_hints).unwrap()
8617 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap()
8618 };
8619
8620 let netgraph = network_graph.read_only();
8621 let route_params = RouteParameters::from_payment_params_and_value(
8622 payment_params, amt_msat);
8623
8624 let route = get_route(
8625 &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::<Vec<_>>()),
8626 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes
8627 ).unwrap();
8628 assert_eq!(route.paths.len(), 1);
8629 assert_eq!(route.get_total_amount(), amt_msat);
8630 }
8631
8632 #[test]
8633 #[rustfmt::skip]
8634 fn candidate_path_min() {
8635 let secp_ctx = Secp256k1::new();
8641 let logger = Arc::new(ln_test_utils::TestLogger::new());
8642 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8643 let gossip_sync = P2PGossipSync::new(Arc::clone(&network_graph), None, Arc::clone(&logger));
8644 let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), Arc::clone(&network_graph), Arc::clone(&logger));
8645 let random_seed_bytes = [42; 32];
8646 let config = UserConfig::default();
8647
8648 let amt_msat = 7_4009_8048;
8650 let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
8651 let first_hops = [get_channel_details(
8652 Some(200), nodes[0], channelmanager::provided_init_features(&config), 2_7345_2000
8653 )];
8654
8655 add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[6], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6);
8656 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
8657 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8658 short_channel_id: 6,
8659 timestamp: 1,
8660 message_flags: 1, channel_flags: 0,
8662 cltv_expiry_delta: (6 << 4) | 0,
8663 htlc_minimum_msat: 0,
8664 htlc_maximum_msat: MAX_VALUE_MSAT,
8665 fee_base_msat: 0,
8666 fee_proportional_millionths: 0,
8667 excess_data: Vec::new()
8668 });
8669 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[0], NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0);
8670
8671 let htlc_min = 2_5165_8240;
8672 let blinded_hints = vec![
8673 dummy_blinded_path(nodes[0], BlindedPayInfo {
8674 fee_base_msat: 1_6778_3453,
8675 fee_proportional_millionths: 0,
8676 htlc_minimum_msat: htlc_min,
8677 htlc_maximum_msat: htlc_min * 100,
8678 cltv_expiry_delta: 10,
8679 features: BlindedHopFeatures::empty(),
8680 })
8681 ];
8682 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8683 let payment_params = PaymentParameters::blinded(blinded_hints.clone())
8684 .with_bolt12_features(bolt12_features.clone()).unwrap();
8685 let route_params = RouteParameters::from_payment_params_and_value(
8686 payment_params, amt_msat);
8687 let netgraph = network_graph.read_only();
8688
8689 if let Err(err) = get_route(
8690 &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::<Vec<_>>()),
8691 Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(),
8692 &random_seed_bytes
8693 ) {
8694 assert_eq!(err, "Failed to find a path to the given destination");
8695 } else { panic!() }
8696 }
8697
8698 #[test]
8699 #[rustfmt::skip]
8700 fn path_contribution_includes_min_htlc_overpay() {
8701 let secp_ctx = Secp256k1::new();
8706 let logger = Arc::new(ln_test_utils::TestLogger::new());
8707 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8708 let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), Arc::clone(&network_graph), Arc::clone(&logger));
8709 let random_seed_bytes = [42; 32];
8710 let config = UserConfig::default();
8711
8712 let amt_msat = 562_0000;
8714 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8715 let first_hops = [
8716 get_channel_details(
8717 Some(83), nodes[0], channelmanager::provided_init_features(&config), 2199_0000,
8718 ),
8719 ];
8720
8721 let htlc_mins = [49_0000, 1125_0000];
8722 let payment_params = {
8723 let mut blinded_hints = Vec::new();
8724 for htlc_min in htlc_mins.iter() {
8725 let payinfo = BlindedPayInfo {
8726 fee_base_msat: 0,
8727 fee_proportional_millionths: 0,
8728 htlc_minimum_msat: *htlc_min,
8729 htlc_maximum_msat: *htlc_min * 100,
8730 cltv_expiry_delta: 10,
8731 features: BlindedHopFeatures::empty(),
8732 };
8733 blinded_hints.push(dummy_blinded_path(nodes[0], payinfo));
8734 }
8735 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8736 PaymentParameters::blinded(blinded_hints.clone())
8737 .with_bolt12_features(bolt12_features.clone()).unwrap()
8738 };
8739
8740 let netgraph = network_graph.read_only();
8741 let route_params = RouteParameters::from_payment_params_and_value(
8742 payment_params, amt_msat);
8743 let route = get_route(
8744 &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::<Vec<_>>()),
8745 Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(),
8746 &random_seed_bytes
8747 ).unwrap();
8748 assert_eq!(route.paths.len(), 1);
8749 assert_eq!(route.get_total_amount(), amt_msat);
8750 }
8751
8752 #[test]
8753 #[rustfmt::skip]
8754 fn first_hop_preferred_over_hint() {
8755 let secp_ctx = Secp256k1::new();
8758 let logger = Arc::new(ln_test_utils::TestLogger::new());
8759 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8760 let gossip_sync = P2PGossipSync::new(Arc::clone(&network_graph), None, Arc::clone(&logger));
8761 let scorer = ln_test_utils::TestScorer::new();
8762 let random_seed_bytes = [42; 32];
8763 let config = UserConfig::default();
8764
8765 let amt_msat = 1_000_000;
8766 let (our_privkey, our_node_id, privkeys, nodes) = get_nodes(&secp_ctx);
8767
8768 add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[0],
8769 ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1);
8770 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
8771 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8772 short_channel_id: 1,
8773 timestamp: 1,
8774 message_flags: 1, channel_flags: 0,
8776 cltv_expiry_delta: 42,
8777 htlc_minimum_msat: 1_000,
8778 htlc_maximum_msat: 10_000_000,
8779 fee_base_msat: 800,
8780 fee_proportional_millionths: 0,
8781 excess_data: Vec::new()
8782 });
8783 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
8784 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8785 short_channel_id: 1,
8786 timestamp: 1,
8787 message_flags: 1, channel_flags: 1,
8789 cltv_expiry_delta: 42,
8790 htlc_minimum_msat: 1_000,
8791 htlc_maximum_msat: 10_000_000,
8792 fee_base_msat: 800,
8793 fee_proportional_millionths: 0,
8794 excess_data: Vec::new()
8795 });
8796
8797 add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[1],
8798 ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 2);
8799 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
8800 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8801 short_channel_id: 2,
8802 timestamp: 2,
8803 message_flags: 1, channel_flags: 0,
8805 cltv_expiry_delta: 42,
8806 htlc_minimum_msat: 1_000,
8807 htlc_maximum_msat: 10_000_000,
8808 fee_base_msat: 800,
8809 fee_proportional_millionths: 0,
8810 excess_data: Vec::new()
8811 });
8812 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
8813 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8814 short_channel_id: 2,
8815 timestamp: 2,
8816 message_flags: 1, channel_flags: 1,
8818 cltv_expiry_delta: 42,
8819 htlc_minimum_msat: 1_000,
8820 htlc_maximum_msat: 10_000_000,
8821 fee_base_msat: 800,
8822 fee_proportional_millionths: 0,
8823 excess_data: Vec::new()
8824 });
8825
8826 let dest_node_id = nodes[2];
8827
8828 let route_hint = RouteHint(vec![RouteHintHop {
8829 src_node_id: our_node_id,
8830 short_channel_id: 44,
8831 fees: RoutingFees {
8832 base_msat: 234,
8833 proportional_millionths: 0,
8834 },
8835 cltv_expiry_delta: 10,
8836 htlc_minimum_msat: None,
8837 htlc_maximum_msat: Some(5_000_000),
8838 },
8839 RouteHintHop {
8840 src_node_id: nodes[0],
8841 short_channel_id: 45,
8842 fees: RoutingFees {
8843 base_msat: 123,
8844 proportional_millionths: 0,
8845 },
8846 cltv_expiry_delta: 10,
8847 htlc_minimum_msat: None,
8848 htlc_maximum_msat: None,
8849 }]);
8850
8851 let payment_params = PaymentParameters::from_node_id(dest_node_id, 42)
8852 .with_route_hints(vec![route_hint]).unwrap()
8853 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap();
8854 let route_params = RouteParameters::from_payment_params_and_value(
8855 payment_params, amt_msat);
8856
8857 let first_hops = [get_channel_details(Some(1), nodes[0],
8860 channelmanager::provided_init_features(&config), 999_999)];
8861
8862 let route = get_route(&our_node_id, &route_params.clone(), &network_graph.read_only(),
8863 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
8864 &Default::default(), &random_seed_bytes).unwrap();
8865 assert_eq!(route.paths.len(), 1);
8866 assert_eq!(route.get_total_amount(), amt_msat);
8867 assert_eq!(route.paths[0].hops.len(), 2);
8868 assert_eq!(route.paths[0].hops[0].short_channel_id, 44);
8869 assert_eq!(route.paths[0].hops[1].short_channel_id, 45);
8870 assert_eq!(route.get_total_fees(), 123);
8871
8872 let mut first_hop = get_channel_details(Some(1), nodes[0], channelmanager::provided_init_features(&config), 999_999);
8875 first_hop.outbound_scid_alias = Some(44);
8876 let first_hops = [first_hop];
8877
8878 let route_res = get_route(&our_node_id, &route_params.clone(), &network_graph.read_only(),
8879 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
8880 &Default::default(), &random_seed_bytes);
8881 assert!(route_res.is_err());
8882
8883 let mut first_hop = get_channel_details(Some(1), nodes[0],
8886 channelmanager::provided_init_features(&config), 10_000_000);
8887 first_hop.outbound_scid_alias = Some(44);
8888 let first_hops = [first_hop];
8889
8890 let route = get_route(&our_node_id, &route_params.clone(), &network_graph.read_only(),
8891 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
8892 &Default::default(), &random_seed_bytes).unwrap();
8893 assert_eq!(route.paths.len(), 1);
8894 assert_eq!(route.get_total_amount(), amt_msat);
8895 assert_eq!(route.paths[0].hops.len(), 2);
8896 assert_eq!(route.paths[0].hops[0].short_channel_id, 1);
8897 assert_eq!(route.paths[0].hops[1].short_channel_id, 45);
8898 assert_eq!(route.get_total_fees(), 123);
8899 }
8900
8901 #[test]
8902 #[rustfmt::skip]
8903 fn test_max_final_contribution() {
8904 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
8910 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
8911 let scorer = ln_test_utils::TestScorer::new();
8912 let random_seed_bytes = [42; 32];
8913
8914 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
8916 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8917 short_channel_id: 1,
8918 timestamp: 2,
8919 message_flags: 1, channel_flags: 0,
8921 cltv_expiry_delta: (1 << 4) | 1,
8922 htlc_minimum_msat: 0,
8923 htlc_maximum_msat: 1_000_000,
8924 fee_base_msat: 0,
8925 fee_proportional_millionths: 0,
8926 excess_data: Vec::new()
8927 });
8928
8929 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
8931 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8932 short_channel_id: 3,
8933 timestamp: 2,
8934 message_flags: 1, channel_flags: 0,
8936 cltv_expiry_delta: (3 << 4) | 1,
8937 htlc_minimum_msat: 0,
8938 htlc_maximum_msat: 1_000_000_000,
8939 fee_base_msat: 0,
8940 fee_proportional_millionths: 0,
8941 excess_data: Vec::new()
8942 });
8943
8944 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
8946 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8947 short_channel_id: 6,
8948 timestamp: 2,
8949 message_flags: 1, channel_flags: 0,
8951 cltv_expiry_delta: (6 << 4) | 1,
8952 htlc_minimum_msat: 0,
8953 htlc_maximum_msat: 1_000_000_000,
8954 fee_base_msat: 0,
8955 fee_proportional_millionths: 1,
8956 excess_data: Vec::new()
8957 });
8958
8959 let config = UserConfig::default();
8963 let payment_params = PaymentParameters::from_node_id(nodes[4], 42)
8964 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
8965 .unwrap();
8966 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1_000_000);
8967 get_route(&our_id, &route_params, &network_graph.read_only(), None,
8968 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap_err();
8969
8970 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
8972 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8973 short_channel_id: 1,
8974 timestamp: 3,
8975 message_flags: 1, channel_flags: 0,
8977 cltv_expiry_delta: (1 << 4) | 1,
8978 htlc_minimum_msat: 0,
8979 htlc_maximum_msat: 1_000_001,
8980 fee_base_msat: 0,
8981 fee_proportional_millionths: 0,
8982 excess_data: Vec::new()
8983 });
8984
8985 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
8987 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
8988 assert_eq!(route.paths.len(), 1);
8989 assert_eq!(route.paths[0].hops.len(), 3);
8990 assert_eq!(route.paths[0].hops[0].short_channel_id, 1);
8991 assert_eq!(route.paths[0].hops[1].short_channel_id, 3);
8992 assert_eq!(route.paths[0].hops[2].short_channel_id, 6);
8993 }
8994
8995 #[test]
8996 #[rustfmt::skip]
8997 fn allow_us_being_first_hint() {
8998 let secp_ctx = Secp256k1::new();
9000 let logger = Arc::new(ln_test_utils::TestLogger::new());
9001 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
9002 let scorer = ln_test_utils::TestScorer::new();
9003 let random_seed_bytes = [42; 32];
9004 let config = UserConfig::default();
9005
9006 let (_, our_node_id, _, nodes) = get_nodes(&secp_ctx);
9007
9008 let amt_msat = 1_000_000;
9009 let dest_node_id = nodes[1];
9010
9011 let first_hops = [
9012 get_channel_details(Some(1), nodes[0], channelmanager::provided_init_features(&config), 10_000_000),
9013 ];
9014
9015 let route_hint = RouteHint(vec![RouteHintHop {
9016 src_node_id: our_node_id,
9017 short_channel_id: 44,
9018 fees: RoutingFees {
9019 base_msat: 123,
9020 proportional_millionths: 0,
9021 },
9022 cltv_expiry_delta: 10,
9023 htlc_minimum_msat: None,
9024 htlc_maximum_msat: None,
9025 }]);
9026
9027 let payment_params = PaymentParameters::from_node_id(dest_node_id, 42)
9028 .with_route_hints(vec![route_hint]).unwrap()
9029 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap();
9030
9031 let route_params = RouteParameters::from_payment_params_and_value(
9032 payment_params, amt_msat);
9033
9034
9035 let route = get_route(&our_node_id, &route_params, &network_graph.read_only(),
9036 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
9037 &Default::default(), &random_seed_bytes).unwrap();
9038
9039 assert_eq!(route.paths.len(), 1);
9040 assert_eq!(route.get_total_amount(), amt_msat);
9041 assert_eq!(route.get_total_fees(), 0);
9042 assert_eq!(route.paths[0].hops.len(), 1);
9043
9044 assert_eq!(route.paths[0].hops[0].short_channel_id, 44);
9045 }
9046
9047 #[test]
9048 fn prefers_paths_by_cost_amt_ratio() {
9049 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
9058 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
9059 let scorer = ln_test_utils::TestScorer::new();
9060 let random_seed_bytes = [42; 32];
9061
9062 let update_1 = UnsignedChannelUpdate {
9064 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9065 short_channel_id: 1,
9066 timestamp: 2,
9067 message_flags: 1, channel_flags: 0,
9069 cltv_expiry_delta: (1 << 4) | 1,
9070 htlc_minimum_msat: 0,
9071 htlc_maximum_msat: 10_000_000,
9072 fee_base_msat: 0,
9073 fee_proportional_millionths: 0,
9074 excess_data: Vec::new(),
9075 };
9076 update_channel(&gossip_sync, &secp_ctx, &our_privkey, update_1);
9077
9078 let update_3 = UnsignedChannelUpdate {
9080 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9081 short_channel_id: 3,
9082 timestamp: 2,
9083 message_flags: 1, channel_flags: 0,
9085 cltv_expiry_delta: (3 << 4) | 1,
9086 htlc_minimum_msat: 0,
9087 htlc_maximum_msat: 1_000_000,
9088 fee_base_msat: 1_000,
9089 fee_proportional_millionths: 0,
9090 excess_data: Vec::new(),
9091 };
9092 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], update_3);
9093
9094 let update_13 = UnsignedChannelUpdate {
9096 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9097 short_channel_id: 13,
9098 timestamp: 2,
9099 message_flags: 1, channel_flags: 0,
9101 cltv_expiry_delta: (13 << 4) | 1,
9102 htlc_minimum_msat: 0,
9103 htlc_maximum_msat: 1_000_000,
9104 fee_base_msat: 1_000,
9105 fee_proportional_millionths: 0,
9106 excess_data: Vec::new(),
9107 };
9108 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], update_13);
9109
9110 let update_4 = UnsignedChannelUpdate {
9112 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9113 short_channel_id: 4,
9114 timestamp: 2,
9115 message_flags: 1, channel_flags: 0,
9117 cltv_expiry_delta: (4 << 4) | 1,
9118 htlc_minimum_msat: 0,
9119 htlc_maximum_msat: 1_000_000,
9120 fee_base_msat: 1_000,
9121 fee_proportional_millionths: 0,
9122 excess_data: Vec::new(),
9123 };
9124 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], update_4);
9125
9126 for i in 0..6 {
9132 let chan_features = ChannelFeatures::from_le_bytes(vec![]);
9135 add_channel(&gossip_sync, &secp_ctx, &privkeys[7], &privkeys[2], chan_features, i + 42);
9136
9137 let update_a = UnsignedChannelUpdate {
9139 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9140 short_channel_id: i + 42,
9141 timestamp: 2,
9142 message_flags: 1, channel_flags: 0,
9144 cltv_expiry_delta: (42 << 4) | 1,
9145 htlc_minimum_msat: 0,
9146 htlc_maximum_msat: 1_000_000,
9147 fee_base_msat: 1_000,
9148 fee_proportional_millionths: 0,
9149 excess_data: Vec::new(),
9150 };
9151 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], update_a);
9152
9153 let update_b = UnsignedChannelUpdate {
9155 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9156 short_channel_id: i + 42,
9157 timestamp: 2,
9158 message_flags: 1, channel_flags: 1,
9160 cltv_expiry_delta: (42 << 4) | 1,
9161 htlc_minimum_msat: 0,
9162 htlc_maximum_msat: 10_000_000,
9163 fee_base_msat: u32::MAX,
9164 fee_proportional_millionths: 0,
9165 excess_data: Vec::new(),
9166 };
9167 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], update_b);
9168 }
9169
9170 let config = UserConfig::default();
9172 let mut payment_params = PaymentParameters::from_node_id(nodes[2], 42)
9173 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
9174 .unwrap();
9175 payment_params.max_channel_saturation_power_of_half = 0;
9176 let route_params =
9177 RouteParameters::from_payment_params_and_value(payment_params, 3_000_000);
9178 let route = get_route(
9179 &our_id,
9180 &route_params,
9181 &network_graph.read_only(),
9182 None,
9183 Arc::clone(&logger),
9184 &scorer,
9185 &Default::default(),
9186 &random_seed_bytes,
9187 )
9188 .unwrap();
9189 assert_eq!(route.paths.len(), 3);
9190 for path in route.paths {
9191 assert_eq!(path.hops.len(), 2);
9192 }
9193
9194 let features_16 = ChannelFeatures::from_le_bytes(id_to_feature_flags(16));
9197 add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[2], features_16, 16);
9198
9199 let update_16_a = UnsignedChannelUpdate {
9201 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9202 short_channel_id: 16,
9203 timestamp: 2,
9204 message_flags: 1, channel_flags: 0,
9206 cltv_expiry_delta: (16 << 4) | 1,
9207 htlc_minimum_msat: 0,
9208 htlc_maximum_msat: 3_000_000,
9209 fee_base_msat: 2_000,
9210 fee_proportional_millionths: 0,
9211 excess_data: Vec::new(),
9212 };
9213 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], update_16_a);
9214
9215 let update_16_b = UnsignedChannelUpdate {
9217 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9218 short_channel_id: 16,
9219 timestamp: 2,
9220 message_flags: 1, channel_flags: 1,
9222 cltv_expiry_delta: (16 << 4) | 1,
9223 htlc_minimum_msat: 0,
9224 htlc_maximum_msat: 10_000_000,
9225 fee_base_msat: u32::MAX,
9226 fee_proportional_millionths: 0,
9227 excess_data: Vec::new(),
9228 };
9229 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], update_16_b);
9230
9231 let route = get_route(
9233 &our_id,
9234 &route_params,
9235 &network_graph.read_only(),
9236 None,
9237 Arc::clone(&logger),
9238 &scorer,
9239 &Default::default(),
9240 &random_seed_bytes,
9241 )
9242 .unwrap();
9243 assert_eq!(route.paths.len(), 1);
9244 assert_eq!(route.paths[0].hops.len(), 2);
9245 assert_eq!(route.paths[0].hops[1].short_channel_id, 16);
9246 }
9247}
9248
9249#[cfg(any(test, ldk_bench))]
9250pub(crate) mod bench_utils {
9251 use super::*;
9252 use bitcoin::hashes::Hash;
9253 use bitcoin::secp256k1::SecretKey;
9254 use std::fs::File;
9255 use std::io::Read;
9256
9257 use crate::chain::transaction::OutPoint;
9258 use crate::ln::chan_utils::make_funding_redeemscript;
9259 use crate::ln::channel_state::{ChannelCounterparty, ChannelShutdownState};
9260 use crate::ln::channelmanager;
9261 use crate::ln::types::ChannelId;
9262 use crate::routing::scoring::{ProbabilisticScorer, ScoreUpdate};
9263 use crate::sync::Arc;
9264 use crate::util::config::UserConfig;
9265 use crate::util::test_utils::TestLogger;
9266
9267 #[rustfmt::skip]
9269 pub(crate) fn get_graph_scorer_file() -> Result<(std::fs::File, std::fs::File), &'static str> {
9270 let load_file = |fname, err_str| {
9271 File::open(fname) .or_else(|_| File::open(&format!("lightning/{}", fname))) .or_else(|_| { let mut path = std::env::current_exe().unwrap();
9276 path.pop(); path.pop(); path.pop(); path.pop(); path.push("lightning");
9281 path.push(fname);
9282 File::open(path)
9283 })
9284 .or_else(|_| { let mut path = std::env::current_exe().unwrap();
9287 path.pop(); path.pop(); path.pop(); path.pop(); path.pop(); path.push("lightning");
9293 path.push(fname);
9294 File::open(path)
9295 })
9296 .map_err(|_| err_str)
9297 };
9298 let graph_res = load_file(
9299 "net_graph-2023-12-10.bin",
9300 "Please fetch https://bitcoin.ninja/ldk-net_graph-v0.0.118-2023-12-10.bin and place it at lightning/net_graph-2023-12-10.bin"
9301 );
9302 let scorer_res = load_file(
9303 "scorer-2023-12-10.bin",
9304 "Please fetch https://bitcoin.ninja/ldk-scorer-v0.0.118-2023-12-10.bin and place it at lightning/scorer-2023-12-10.bin"
9305 );
9306 #[cfg(require_route_graph_test)]
9307 return Ok((graph_res.unwrap(), scorer_res.unwrap()));
9308 #[cfg(not(require_route_graph_test))]
9309 return Ok((graph_res?, scorer_res?));
9310 }
9311
9312 pub(crate) fn read_graph_scorer(
9313 logger: &TestLogger,
9314 ) -> Result<
9315 (
9316 Arc<NetworkGraph<&TestLogger>>,
9317 ProbabilisticScorer<Arc<NetworkGraph<&TestLogger>>, &TestLogger>,
9318 ),
9319 &'static str,
9320 > {
9321 let (mut graph_file, mut scorer_file) = get_graph_scorer_file()?;
9322 let mut graph_buffer = Vec::new();
9323 let mut scorer_buffer = Vec::new();
9324 graph_file.read_to_end(&mut graph_buffer).unwrap();
9325 scorer_file.read_to_end(&mut scorer_buffer).unwrap();
9326 let graph = Arc::new(NetworkGraph::read(&mut &graph_buffer[..], logger).unwrap());
9327 let scorer_args = (Default::default(), Arc::clone(&graph), logger);
9328 let scorer = ProbabilisticScorer::read(&mut &scorer_buffer[..], scorer_args).unwrap();
9329 Ok((graph, scorer))
9330 }
9331
9332 pub(crate) fn payer_pubkey() -> PublicKey {
9333 let secp_ctx = Secp256k1::new();
9334 PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap())
9335 }
9336
9337 #[inline]
9338 #[rustfmt::skip]
9339 pub(crate) fn first_hop(node_id: PublicKey) -> ChannelDetails {
9340 #[allow(deprecated)] ChannelDetails {
9342 channel_id: ChannelId::new_zero(),
9343 counterparty: ChannelCounterparty {
9344 features: channelmanager::provided_init_features(&UserConfig::default()),
9345 node_id,
9346 unspendable_punishment_reserve: 0,
9347 forwarding_info: None,
9348 outbound_htlc_minimum_msat: None,
9349 outbound_htlc_maximum_msat: None,
9350 },
9351 funding_txo: Some(OutPoint {
9352 txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0
9353 }),
9354 funding_redeem_script: Some(make_funding_redeemscript(
9355 &PublicKey::from_slice(&[2; 33]).unwrap(),
9356 &PublicKey::from_slice(&[2; 33]).unwrap(),
9357 )),
9358 channel_type: None,
9359 short_channel_id: Some(1),
9360 inbound_scid_alias: None,
9361 outbound_scid_alias: None,
9362 channel_value_satoshis: 10_000_000_000,
9363 user_channel_id: 0,
9364 outbound_capacity_msat: 10_000_000_000,
9365 next_outbound_htlc_minimum_msat: 0,
9366 next_outbound_htlc_limit_msat: 10_000_000_000,
9367 inbound_capacity_msat: 0,
9368 unspendable_punishment_reserve: None,
9369 confirmations_required: None,
9370 confirmations: None,
9371 force_close_spend_delay: None,
9372 is_outbound: true,
9373 is_channel_ready: true,
9374 is_usable: true,
9375 is_announced: true,
9376 inbound_htlc_minimum_msat: None,
9377 inbound_htlc_maximum_msat: None,
9378 config: None,
9379 feerate_sat_per_1000_weight: None,
9380 channel_shutdown_state: Some(ChannelShutdownState::NotShuttingDown),
9381 pending_inbound_htlcs: Vec::new(),
9382 pending_outbound_htlcs: Vec::new(),
9383 }
9384 }
9385
9386 #[rustfmt::skip]
9387 pub(crate) fn generate_test_routes<S: ScoreLookUp + ScoreUpdate>(graph: &NetworkGraph<&TestLogger>, scorer: &mut S,
9388 score_params: &S::ScoreParams, features: Bolt11InvoiceFeatures, mut seed: u64,
9389 starting_amount: u64, route_count: usize,
9390 ) -> Vec<(ChannelDetails, PaymentParameters, u64)> {
9391 let payer = payer_pubkey();
9392 let random_seed_bytes = [42; 32];
9393
9394 let mut nodes = graph.read_only().nodes().clone();
9395 let mut route_endpoints = Vec::new();
9396 for _ in 0..route_count {
9397 loop {
9398 seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0;
9399 let src_idx = (seed as usize) % nodes.len();
9400 let src_key = nodes.range(..).skip(src_idx).next().unwrap().0;
9401 let src = PublicKey::from_slice(src_key.as_slice()).unwrap();
9402
9403 seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0;
9404 let dst_idx = (seed as usize) % nodes.len();
9405 let dst_key = nodes.range(..).skip(dst_idx).next().unwrap().0;
9406 let dst = PublicKey::from_slice(dst_key.as_slice()).unwrap();
9407
9408 let params = PaymentParameters::from_node_id(dst, 42)
9409 .with_bolt11_features(features.clone()).unwrap();
9410 let first_hop = first_hop(src);
9411 let amt_msat = starting_amount + seed % 1_000_000;
9412 let route_params = RouteParameters::from_payment_params_and_value(
9413 params.clone(), amt_msat);
9414 let path_exists =
9415 get_route(&payer, &route_params, &graph.read_only(), Some(&[&first_hop]),
9416 &TestLogger::new(), scorer, score_params, &random_seed_bytes).is_ok();
9417 if path_exists {
9418 route_endpoints.push((first_hop, params, amt_msat));
9419 break;
9420 }
9421 }
9422 }
9423
9424 route_endpoints
9425 }
9426}
9427
9428#[cfg(ldk_bench)]
9429pub mod benches {
9430 use super::*;
9431 use crate::ln::channelmanager;
9432 use crate::routing::gossip::NetworkGraph;
9433 use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScoringFeeParameters};
9434 use crate::routing::scoring::{ScoreLookUp, ScoreUpdate};
9435 use crate::types::features::Bolt11InvoiceFeatures;
9436 use crate::util::config::UserConfig;
9437 use crate::util::logger::{Logger, Record};
9438 use crate::util::test_utils::TestLogger;
9439
9440 use criterion::Criterion;
9441
9442 struct DummyLogger {}
9443 impl Logger for DummyLogger {
9444 fn log(&self, _record: Record) {}
9445 }
9446
9447 #[rustfmt::skip]
9448 pub fn generate_routes_with_zero_penalty_scorer(bench: &mut Criterion) {
9449 let logger = TestLogger::new();
9450 let (network_graph, _) = bench_utils::read_graph_scorer(&logger).unwrap();
9451 let scorer = FixedPenaltyScorer::with_penalty(0);
9452 generate_routes(bench, &network_graph, scorer, &Default::default(),
9453 Bolt11InvoiceFeatures::empty(), 0, "generate_routes_with_zero_penalty_scorer");
9454 }
9455
9456 #[rustfmt::skip]
9457 pub fn generate_mpp_routes_with_zero_penalty_scorer(bench: &mut Criterion) {
9458 let logger = TestLogger::new();
9459 let (network_graph, _) = bench_utils::read_graph_scorer(&logger).unwrap();
9460 let scorer = FixedPenaltyScorer::with_penalty(0);
9461 generate_routes(bench, &network_graph, scorer, &Default::default(),
9462 channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0,
9463 "generate_mpp_routes_with_zero_penalty_scorer");
9464 }
9465
9466 #[rustfmt::skip]
9467 pub fn generate_routes_with_probabilistic_scorer(bench: &mut Criterion) {
9468 let logger = TestLogger::new();
9469 let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap();
9470 let params = ProbabilisticScoringFeeParameters::default();
9471 generate_routes(bench, &network_graph, scorer, ¶ms, Bolt11InvoiceFeatures::empty(), 0,
9472 "generate_routes_with_probabilistic_scorer");
9473 }
9474
9475 #[rustfmt::skip]
9476 pub fn generate_mpp_routes_with_probabilistic_scorer(bench: &mut Criterion) {
9477 let logger = TestLogger::new();
9478 let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap();
9479 let params = ProbabilisticScoringFeeParameters::default();
9480 generate_routes(bench, &network_graph, scorer, ¶ms,
9481 channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0,
9482 "generate_mpp_routes_with_probabilistic_scorer");
9483 }
9484
9485 #[rustfmt::skip]
9486 pub fn generate_large_mpp_routes_with_probabilistic_scorer(bench: &mut Criterion) {
9487 let logger = TestLogger::new();
9488 let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap();
9489 let params = ProbabilisticScoringFeeParameters::default();
9490 generate_routes(bench, &network_graph, scorer, ¶ms,
9491 channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 100_000_000,
9492 "generate_large_mpp_routes_with_probabilistic_scorer");
9493 }
9494
9495 #[rustfmt::skip]
9496 pub fn generate_routes_with_nonlinear_probabilistic_scorer(bench: &mut Criterion) {
9497 let logger = TestLogger::new();
9498 let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap();
9499 let mut params = ProbabilisticScoringFeeParameters::default();
9500 params.linear_success_probability = false;
9501 generate_routes(bench, &network_graph, scorer, ¶ms,
9502 channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0,
9503 "generate_routes_with_nonlinear_probabilistic_scorer");
9504 }
9505
9506 #[rustfmt::skip]
9507 pub fn generate_mpp_routes_with_nonlinear_probabilistic_scorer(bench: &mut Criterion) {
9508 let logger = TestLogger::new();
9509 let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap();
9510 let mut params = ProbabilisticScoringFeeParameters::default();
9511 params.linear_success_probability = false;
9512 generate_routes(bench, &network_graph, scorer, ¶ms,
9513 channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0,
9514 "generate_mpp_routes_with_nonlinear_probabilistic_scorer");
9515 }
9516
9517 #[rustfmt::skip]
9518 pub fn generate_large_mpp_routes_with_nonlinear_probabilistic_scorer(bench: &mut Criterion) {
9519 let logger = TestLogger::new();
9520 let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap();
9521 let mut params = ProbabilisticScoringFeeParameters::default();
9522 params.linear_success_probability = false;
9523 generate_routes(bench, &network_graph, scorer, ¶ms,
9524 channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 100_000_000,
9525 "generate_large_mpp_routes_with_nonlinear_probabilistic_scorer");
9526 }
9527
9528 #[rustfmt::skip]
9529 fn generate_routes<S: ScoreLookUp + ScoreUpdate>(
9530 bench: &mut Criterion, graph: &NetworkGraph<&TestLogger>, mut scorer: S,
9531 score_params: &S::ScoreParams, features: Bolt11InvoiceFeatures, starting_amount: u64,
9532 bench_name: &'static str,
9533 ) {
9534 let route_endpoints = bench_utils::generate_test_routes(graph, &mut scorer, score_params, features, 0xdeadbeef, starting_amount, 50);
9536
9537 do_route_bench(bench, graph, scorer, score_params, bench_name, route_endpoints);
9539 }
9540
9541 #[inline(never)]
9542 #[rustfmt::skip]
9543 fn do_route_bench<S: ScoreLookUp + ScoreUpdate>(
9544 bench: &mut Criterion, graph: &NetworkGraph<&TestLogger>, scorer: S,
9545 score_params: &S::ScoreParams, bench_name: &'static str,
9546 route_endpoints: Vec<(ChannelDetails, PaymentParameters, u64)>,
9547 ) {
9548 let payer = bench_utils::payer_pubkey();
9549 let random_seed_bytes = [42; 32];
9550
9551 let mut idx = 0;
9552 bench.bench_function(bench_name, |b| b.iter(|| {
9553 let (first_hop, params, amt) = &route_endpoints[idx % route_endpoints.len()];
9554 let route_params = RouteParameters::from_payment_params_and_value(params.clone(), *amt);
9555 assert!(get_route(&payer, &route_params, &graph.read_only(), Some(&[first_hop]),
9556 &DummyLogger{}, &scorer, score_params, &random_seed_bytes).is_ok());
9557 idx += 1;
9558 }));
9559 }
9560}