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.get_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]
2237 fn max_final_value_msat(
2238 &self, used_liquidities: &HashMap<CandidateHopId, u64>, channel_saturation_pow_half: u8
2239 ) -> Result<(usize, u64), usize> {
2240 let mut max_path_contribution = (0, u64::MAX);
2241 for (idx, (hop, _)) in self.hops.iter().enumerate() {
2242 let hop_effective_capacity_msat = hop.candidate.effective_capacity();
2243 let hop_max_msat = max_htlc_from_capacity(
2244 hop_effective_capacity_msat, channel_saturation_pow_half
2245 ).saturating_sub(*used_liquidities.get(&hop.candidate.id()).unwrap_or(&0_u64));
2246
2247 let next_hops_feerates_iter = self.hops
2248 .iter()
2249 .skip(idx + 1)
2250 .map(|(hop, _)| hop.candidate.fees());
2251
2252 let (next_hops_aggregated_base, next_hops_aggregated_prop) =
2255 crate::blinded_path::payment::compute_aggregated_base_prop_fee(next_hops_feerates_iter)
2256 .map_err(|_| idx + 1)?;
2257
2258 let hop_max_final_value_contribution = (hop_max_msat as u128)
2260 .checked_sub(next_hops_aggregated_base as u128)
2261 .and_then(|f| f.checked_mul(1_000_000))
2262 .and_then(|f| f.checked_add(next_hops_aggregated_prop as u128))
2263 .map(|f| f / ((next_hops_aggregated_prop as u128).saturating_add(1_000_000)));
2264
2265 if let Some(hop_contribution) = hop_max_final_value_contribution {
2266 let hop_contribution: u64 = hop_contribution.try_into().unwrap_or(u64::MAX);
2267 if hop_contribution <= max_path_contribution.1 {
2268 max_path_contribution = (idx, hop_contribution);
2269 }
2270 } else { debug_assert!(false); }
2271 }
2272
2273 Ok(max_path_contribution)
2274 }
2275}
2276
2277fn mark_candidate_liquidity_exhausted(
2278 used_liquidities: &mut HashMap<CandidateHopId, u64>, candidate: &CandidateRouteHop,
2279) {
2280 let exhausted = u64::max_value();
2281 if let Some(scid) = candidate.short_channel_id() {
2282 *used_liquidities.entry(CandidateHopId::Clear((scid, false))).or_default() = exhausted;
2283 *used_liquidities.entry(CandidateHopId::Clear((scid, true))).or_default() = exhausted;
2284 } else {
2285 *used_liquidities.entry(candidate.id()).or_default() = exhausted;
2286 }
2287}
2288
2289#[inline(always)]
2290#[rustfmt::skip]
2292fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option<u64> {
2293 amount_msat.checked_mul(channel_fees.proportional_millionths as u64)
2294 .and_then(|part| (channel_fees.base_msat as u64).checked_add(part / 1_000_000))
2295}
2296
2297#[inline(always)]
2298#[rustfmt::skip]
2301fn compute_fees_saturating(amount_msat: u64, channel_fees: RoutingFees) -> u64 {
2302 amount_msat.checked_mul(channel_fees.proportional_millionths as u64)
2303 .map(|prop| prop / 1_000_000).unwrap_or(u64::max_value())
2304 .saturating_add(channel_fees.base_msat as u64)
2305}
2306
2307fn default_node_features() -> NodeFeatures {
2313 let mut features = NodeFeatures::empty();
2314 features.set_variable_length_onion_optional();
2315 features
2316}
2317
2318struct LoggedPayeePubkey(Option<PublicKey>);
2319impl fmt::Display for LoggedPayeePubkey {
2320 #[rustfmt::skip]
2321 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2322 match self.0 {
2323 Some(pk) => {
2324 "payee node id ".fmt(f)?;
2325 pk.fmt(f)
2326 },
2327 None => {
2328 "blinded payee".fmt(f)
2329 },
2330 }
2331 }
2332}
2333
2334struct LoggedCandidateHop<'a>(&'a CandidateRouteHop<'a>);
2335impl<'a> fmt::Display for LoggedCandidateHop<'a> {
2336 #[rustfmt::skip]
2337 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2338 match self.0 {
2339 CandidateRouteHop::Blinded(BlindedPathCandidate { hint, .. }) | CandidateRouteHop::OneHopBlinded(OneHopBlindedPathCandidate { hint, .. }) => {
2340 "blinded route hint with introduction node ".fmt(f)?;
2341 match hint.introduction_node() {
2342 IntroductionNode::NodeId(pubkey) => write!(f, "id {}", pubkey)?,
2343 IntroductionNode::DirectedShortChannelId(direction, scid) => {
2344 match direction {
2345 Direction::NodeOne => {
2346 write!(f, "one on channel with SCID {}", scid)?;
2347 },
2348 Direction::NodeTwo => {
2349 write!(f, "two on channel with SCID {}", scid)?;
2350 },
2351 }
2352 }
2353 }
2354 " and blinding point ".fmt(f)?;
2355 hint.blinding_point().fmt(f)
2356 },
2357 CandidateRouteHop::FirstHop(_) => {
2358 "first hop with SCID ".fmt(f)?;
2359 self.0.short_channel_id().unwrap().fmt(f)
2360 },
2361 CandidateRouteHop::PrivateHop(_) => {
2362 "route hint with SCID ".fmt(f)?;
2363 self.0.short_channel_id().unwrap().fmt(f)
2364 },
2365 _ => {
2366 "SCID ".fmt(f)?;
2367 self.0.short_channel_id().unwrap().fmt(f)
2368 },
2369 }
2370 }
2371}
2372
2373#[inline]
2374#[rustfmt::skip]
2375fn sort_first_hop_channels(
2376 channels: &mut Vec<&ChannelDetails>, used_liquidities: &HashMap<CandidateHopId, u64>,
2377 recommended_value_msat: u64, our_node_pubkey: &PublicKey
2378) {
2379 channels.sort_unstable_by(|chan_a, chan_b| {
2393 let chan_a_outbound_limit_msat = chan_a.next_outbound_htlc_limit_msat
2394 .saturating_sub(*used_liquidities.get(&CandidateHopId::Clear((chan_a.get_outbound_payment_scid().unwrap(),
2395 our_node_pubkey < &chan_a.counterparty.node_id))).unwrap_or(&0));
2396 let chan_b_outbound_limit_msat = chan_b.next_outbound_htlc_limit_msat
2397 .saturating_sub(*used_liquidities.get(&CandidateHopId::Clear((chan_b.get_outbound_payment_scid().unwrap(),
2398 our_node_pubkey < &chan_b.counterparty.node_id))).unwrap_or(&0));
2399 if chan_b_outbound_limit_msat < recommended_value_msat || chan_a_outbound_limit_msat < recommended_value_msat {
2400 chan_b_outbound_limit_msat.cmp(&chan_a_outbound_limit_msat)
2402 } else {
2403 chan_a_outbound_limit_msat.cmp(&chan_b_outbound_limit_msat)
2405 }
2406 });
2407}
2408
2409#[rustfmt::skip]
2435pub fn find_route<L: Deref, GL: Deref, S: ScoreLookUp>(
2436 our_node_pubkey: &PublicKey, route_params: &RouteParameters,
2437 network_graph: &NetworkGraph<GL>, first_hops: Option<&[&ChannelDetails]>, logger: L,
2438 scorer: &S, score_params: &S::ScoreParams, random_seed_bytes: &[u8; 32]
2439) -> Result<Route, &'static str>
2440where L::Target: Logger, GL::Target: Logger {
2441 let graph_lock = network_graph.read_only();
2442 let mut route = get_route(our_node_pubkey, &route_params, &graph_lock, first_hops, logger,
2443 scorer, score_params, random_seed_bytes)?;
2444 add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes);
2445 Ok(route)
2446}
2447
2448#[rustfmt::skip]
2449pub(crate) fn get_route<L: Deref, S: ScoreLookUp>(
2450 our_node_pubkey: &PublicKey, route_params: &RouteParameters, network_graph: &ReadOnlyNetworkGraph,
2451 first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S, score_params: &S::ScoreParams,
2452 _random_seed_bytes: &[u8; 32]
2453) -> Result<Route, &'static str>
2454where L::Target: Logger {
2455
2456 let payment_params = &route_params.payment_params;
2457 let max_path_length = core::cmp::min(payment_params.max_path_length, MAX_PATH_LENGTH_ESTIMATE);
2458 let final_value_msat = route_params.final_value_msat;
2459 let payee_node_id_opt = payment_params.payee.node_id().map(|pk| NodeId::from_pubkey(&pk));
2463 const DUMMY_BLINDED_PAYEE_ID: [u8; 33] = [2; 33];
2464 let maybe_dummy_payee_pk = payment_params.payee.node_id().unwrap_or_else(|| PublicKey::from_slice(&DUMMY_BLINDED_PAYEE_ID).unwrap());
2465 let maybe_dummy_payee_node_id = NodeId::from_pubkey(&maybe_dummy_payee_pk);
2466 let our_node_id = NodeId::from_pubkey(&our_node_pubkey);
2467
2468 if payee_node_id_opt.map_or(false, |payee| payee == our_node_id) {
2469 return Err("Cannot generate a route to ourselves");
2470 }
2471 if our_node_id == maybe_dummy_payee_node_id {
2472 return Err("Invalid origin node id provided, use a different one");
2473 }
2474
2475 if final_value_msat > MAX_VALUE_MSAT {
2476 return Err("Cannot generate a route of more value than all existing satoshis");
2477 }
2478
2479 if final_value_msat == 0 {
2480 return Err("Cannot send a payment of 0 msat");
2481 }
2482
2483 let final_cltv_expiry_delta = payment_params.payee.final_cltv_expiry_delta().unwrap_or(0);
2484 if payment_params.max_total_cltv_expiry_delta <= final_cltv_expiry_delta {
2485 return Err("Can't find a route where the maximum total CLTV expiry delta is below the final CLTV expiry.");
2486 }
2487
2488 let network_channels = network_graph.channels();
2545 let network_nodes = network_graph.nodes();
2546
2547 if payment_params.max_path_count == 0 {
2548 return Err("Can't find a route with no paths allowed.");
2549 }
2550
2551 let allow_mpp = if payment_params.max_path_count == 1 {
2555 false
2556 } else if payment_params.payee.supports_basic_mpp() {
2557 true
2558 } else if let Some(payee) = payee_node_id_opt {
2559 network_nodes.get(&payee).map_or(false, |node| node.announcement_info.as_ref().map_or(false,
2560 |info| info.features().supports_basic_mpp()))
2561 } else { false };
2562
2563 let max_total_routing_fee_msat = route_params.max_total_routing_fee_msat.unwrap_or(u64::max_value());
2564
2565 let first_hop_count = first_hops.map(|hops| hops.len()).unwrap_or(0);
2566 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",
2567 our_node_pubkey, LoggedPayeePubkey(payment_params.payee.node_id()),
2568 if allow_mpp { "with" } else { "without" },
2569 first_hop_count, if first_hops.is_some() { "" } else { "not " },
2570 network_graph.nodes().len(), network_graph.channels().len(),
2571 max_total_routing_fee_msat);
2572
2573 if first_hop_count < 10 {
2574 if let Some(hops) = first_hops {
2575 for hop in hops {
2576 log_trace!(
2577 logger,
2578 " First hop through {}/{} can send between {}msat and {}msat (inclusive).",
2579 hop.counterparty.node_id,
2580 hop.get_outbound_payment_scid().unwrap_or(0),
2581 hop.next_outbound_htlc_minimum_msat,
2582 hop.next_outbound_htlc_limit_msat
2583 );
2584 }
2585 }
2586 }
2587
2588 let mut node_counter_builder = NodeCountersBuilder::new(&network_graph);
2589
2590 let payer_node_counter = node_counter_builder.select_node_counter_for_pubkey(*our_node_pubkey);
2591 let payee_node_counter = node_counter_builder.select_node_counter_for_pubkey(maybe_dummy_payee_pk);
2592
2593 for route in payment_params.payee.unblinded_route_hints().iter() {
2594 for hop in route.0.iter() {
2595 node_counter_builder.select_node_counter_for_pubkey(hop.src_node_id);
2596 }
2597 }
2598
2599 let mut first_hop_targets: HashMap<_, (Vec<&ChannelDetails>, u32)> =
2606 hash_map_with_capacity(if first_hops.is_some() { first_hops.as_ref().unwrap().len() } else { 0 });
2607 if let Some(hops) = first_hops {
2608 for chan in hops {
2609 if chan.get_outbound_payment_scid().is_none() {
2610 panic!("first_hops should be filled in with usable channels, not pending ones");
2611 }
2612 if chan.counterparty.node_id == *our_node_pubkey {
2613 return Err("First hop cannot have our_node_pubkey as a destination.");
2614 }
2615 let counterparty_id = NodeId::from_pubkey(&chan.counterparty.node_id);
2616 first_hop_targets
2617 .entry(counterparty_id)
2618 .or_insert_with(|| {
2619 let node_counter = node_counter_builder.select_node_counter_for_id(counterparty_id);
2621 (Vec::new(), node_counter)
2622 })
2623 .0.push(chan);
2624 }
2625 if first_hop_targets.is_empty() {
2626 return Err("Cannot route when there are no outbound routes away from us");
2627 }
2628 }
2629
2630 let node_counters = node_counter_builder.build();
2631
2632 let introduction_node_id_cache = calculate_blinded_path_intro_points(
2633 &payment_params, &node_counters, network_graph, &logger, our_node_id, &first_hop_targets,
2634 )?;
2635
2636 let mut last_hop_candidates =
2637 hash_map_with_capacity(payment_params.payee.unblinded_route_hints().len());
2638 for route in payment_params.payee.unblinded_route_hints().iter()
2639 .filter(|route| !route.0.is_empty())
2640 {
2641 let hop_iter = route.0.iter().rev();
2642 let prev_hop_iter = core::iter::once(&maybe_dummy_payee_pk).chain(
2643 route.0.iter().skip(1).rev().map(|hop| &hop.src_node_id));
2644
2645 for (hop, prev_hop_id) in hop_iter.zip(prev_hop_iter) {
2646 let (target, private_target_node_counter) =
2647 node_counters.private_node_counter_from_pubkey(&prev_hop_id)
2648 .ok_or_else(|| {
2649 debug_assert!(false);
2650 "We should always have private target node counters available"
2651 })?;
2652 let (_src_id, private_source_node_counter) =
2653 node_counters.private_node_counter_from_pubkey(&hop.src_node_id)
2654 .ok_or_else(|| {
2655 debug_assert!(false);
2656 "We should always have private source node counters available"
2657 })?;
2658
2659 if let Some((first_channels, _)) = first_hop_targets.get(target) {
2660 let matches_an_scid = |d: &&ChannelDetails|
2661 d.outbound_scid_alias == Some(hop.short_channel_id) || d.short_channel_id == Some(hop.short_channel_id);
2662 if first_channels.iter().any(matches_an_scid) {
2663 log_trace!(logger, "Ignoring route hint with SCID {} (and any previous) due to it being a direct channel of ours.",
2664 hop.short_channel_id);
2665 break;
2666 }
2667 }
2668
2669 let candidate = network_channels
2670 .get(&hop.short_channel_id)
2671 .and_then(|channel| channel.as_directed_to(target))
2672 .map(|(info, _)| CandidateRouteHop::PublicHop(PublicHopCandidate {
2673 info,
2674 short_channel_id: hop.short_channel_id,
2675 }))
2676 .unwrap_or_else(|| CandidateRouteHop::PrivateHop(PrivateHopCandidate {
2677 hint: hop, target_node_id: target,
2678 source_node_counter: *private_source_node_counter,
2679 target_node_counter: *private_target_node_counter,
2680 }));
2681
2682 last_hop_candidates.entry(private_target_node_counter).or_insert_with(Vec::new).push(candidate);
2683 }
2684 }
2685
2686 let mut targets: BinaryHeap<RouteGraphNode> = BinaryHeap::new();
2690
2691 let dist_len = node_counters.max_counter() + 1;
2694 let mut dist: Vec<Option<PathBuildingHop>> = vec![None; dist_len as usize];
2695
2696 let mut hit_minimum_limit;
2700
2701 const ROUTE_CAPACITY_PROVISION_FACTOR: u64 = 3;
2706 let recommended_value_msat = final_value_msat * ROUTE_CAPACITY_PROVISION_FACTOR as u64;
2707 let mut path_value_msat = final_value_msat;
2708
2709 let minimal_value_contribution_msat: u64 = if allow_mpp {
2719 (final_value_msat + (payment_params.max_path_count as u64 - 1)) / payment_params.max_path_count as u64
2720 } else {
2721 final_value_msat
2722 };
2723
2724 let mut channel_saturation_pow_half = payment_params.max_channel_saturation_power_of_half;
2728
2729 let max_total_cltv_expiry_delta: u16 =
2733 (payment_params.max_total_cltv_expiry_delta - final_cltv_expiry_delta)
2734 .checked_sub(2*MEDIAN_HOP_CLTV_EXPIRY_DELTA)
2735 .unwrap_or(payment_params.max_total_cltv_expiry_delta - final_cltv_expiry_delta)
2736 .try_into()
2737 .unwrap_or(u16::MAX);
2738
2739 let mut used_liquidities: HashMap<CandidateHopId, u64> =
2745 hash_map_with_capacity(network_nodes.len());
2746
2747 let mut already_collected_value_msat = 0;
2750
2751 for (_, (channels, _)) in first_hop_targets.iter_mut() {
2752 sort_first_hop_channels(channels, &used_liquidities, recommended_value_msat,
2753 our_node_pubkey);
2754 }
2755
2756 log_trace!(logger, "Building path from {} to payer {} for value {} msat.",
2757 LoggedPayeePubkey(payment_params.payee.node_id()), our_node_pubkey, final_value_msat);
2758
2759 let mut num_ignored_value_contribution: u32 = 0;
2761 let mut num_ignored_path_length_limit: u32 = 0;
2762 let mut num_ignored_cltv_delta_limit: u32 = 0;
2763 let mut num_ignored_previously_failed: u32 = 0;
2764 let mut num_ignored_total_fee_limit: u32 = 0;
2765 let mut num_ignored_avoid_overpayment: u32 = 0;
2766 let mut num_ignored_htlc_minimum_msat_limit: u32 = 0;
2767
2768 macro_rules! add_entry {
2769 ( $candidate: expr, $next_hops_fee_msat: expr,
2774 $next_hops_value_contribution: expr, $next_hops_path_htlc_minimum_msat: expr,
2775 $next_hops_path_penalty_msat: expr, $next_hops_cltv_delta: expr, $next_hops_path_length: expr ) => { {
2776 let mut hop_contribution_amt_msat = None;
2779
2780 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
2781 if let Some(counter) = $candidate.target_node_counter() {
2782 if let Some(node) = &mut dist[counter as usize] {
2786 node.best_path_from_hop_selected = true;
2787 } else if counter != payee_node_counter {
2788 panic!("No dist entry for target node counter {}", counter);
2789 }
2790 }
2791
2792 let src_node_id = $candidate.source();
2797 if Some(src_node_id) != $candidate.target() {
2798 let scid_opt = $candidate.short_channel_id();
2799 let effective_capacity = $candidate.effective_capacity();
2800 let htlc_maximum_msat = max_htlc_from_capacity(effective_capacity, channel_saturation_pow_half);
2801
2802 if let Some(mut available_value_contribution_msat) = htlc_maximum_msat.checked_sub($next_hops_fee_msat) {
2810 let cltv_expiry_delta = $candidate.cltv_expiry_delta();
2811 let htlc_minimum_msat = $candidate.htlc_minimum_msat();
2812 let used_liquidity_msat = used_liquidities
2813 .get(&$candidate.id())
2814 .map_or(0, |used_liquidity_msat| {
2815 available_value_contribution_msat = available_value_contribution_msat
2816 .saturating_sub(*used_liquidity_msat);
2817 *used_liquidity_msat
2818 });
2819
2820 let path_length_to_node = $next_hops_path_length
2822 + if $candidate.blinded_hint_idx().is_some() { 0 } else { 1 };
2823 let exceeds_max_path_length = path_length_to_node > max_path_length;
2824
2825 let hop_total_cltv_delta = ($next_hops_cltv_delta as u32)
2827 .saturating_add(cltv_expiry_delta);
2828 let exceeds_cltv_delta_limit = hop_total_cltv_delta > max_total_cltv_expiry_delta as u32;
2829
2830 let value_contribution_msat = cmp::min(available_value_contribution_msat, $next_hops_value_contribution);
2831 let contributes_sufficient_value = value_contribution_msat >= minimal_value_contribution_msat;
2833 let amount_to_transfer_over_msat: u64 = match value_contribution_msat.checked_add($next_hops_fee_msat) {
2835 Some(result) => result,
2836 None => unreachable!(),
2838 };
2839 #[allow(unused_comparisons)] let over_path_minimum_msat = amount_to_transfer_over_msat >= htlc_minimum_msat &&
2841 amount_to_transfer_over_msat >= $next_hops_path_htlc_minimum_msat;
2842
2843 #[allow(unused_comparisons)] let may_overpay_to_meet_path_minimum_msat =
2845 (amount_to_transfer_over_msat < htlc_minimum_msat &&
2846 recommended_value_msat >= htlc_minimum_msat) ||
2847 (amount_to_transfer_over_msat < $next_hops_path_htlc_minimum_msat &&
2848 recommended_value_msat >= $next_hops_path_htlc_minimum_msat);
2849
2850 let payment_failed_on_this_channel = match scid_opt {
2851 Some(scid) => payment_params.previously_failed_channels.contains(&scid),
2852 None => match $candidate.blinded_hint_idx() {
2853 Some(idx) => {
2854 payment_params.previously_failed_blinded_path_idxs.contains(&(idx as u64))
2855 },
2856 None => false,
2857 },
2858 };
2859
2860 let (should_log_candidate, first_hop_details) = match $candidate {
2861 CandidateRouteHop::FirstHop(hop) => (true, Some(hop.details)),
2862 CandidateRouteHop::PrivateHop(_) => (true, None),
2863 CandidateRouteHop::Blinded(_) => (true, None),
2864 CandidateRouteHop::OneHopBlinded(_) => (true, None),
2865 _ => (false, None),
2866 };
2867
2868 if !contributes_sufficient_value {
2873 if should_log_candidate {
2874 log_trace!(logger, "Ignoring {} due to insufficient value contribution (channel max {:?}).",
2875 LoggedCandidateHop(&$candidate),
2876 effective_capacity);
2877 }
2878 num_ignored_value_contribution += 1;
2879 } else if exceeds_max_path_length {
2880 if should_log_candidate {
2881 log_trace!(logger, "Ignoring {} due to exceeding maximum path length limit.", LoggedCandidateHop(&$candidate));
2882 }
2883 num_ignored_path_length_limit += 1;
2884 } else if exceeds_cltv_delta_limit {
2885 if should_log_candidate {
2886 log_trace!(logger, "Ignoring {} due to exceeding CLTV delta limit.", LoggedCandidateHop(&$candidate));
2887
2888 if let Some(_) = first_hop_details {
2889 log_trace!(logger,
2890 "First hop candidate cltv_expiry_delta: {}. Limit: {}",
2891 hop_total_cltv_delta,
2892 max_total_cltv_expiry_delta,
2893 );
2894 }
2895 }
2896 num_ignored_cltv_delta_limit += 1;
2897 } else if payment_failed_on_this_channel {
2898 if should_log_candidate {
2899 log_trace!(logger, "Ignoring {} due to a failed previous payment attempt.", LoggedCandidateHop(&$candidate));
2900 }
2901 num_ignored_previously_failed += 1;
2902 } else if may_overpay_to_meet_path_minimum_msat {
2903 if should_log_candidate {
2904 log_trace!(logger,
2905 "Ignoring {} to avoid overpaying to meet htlc_minimum_msat limit ({}).",
2906 LoggedCandidateHop(&$candidate), $candidate.htlc_minimum_msat());
2907 }
2908 num_ignored_avoid_overpayment += 1;
2909 hit_minimum_limit = true;
2910 } else if over_path_minimum_msat {
2911 let curr_min = cmp::max(
2916 $next_hops_path_htlc_minimum_msat, htlc_minimum_msat
2917 );
2918 let src_node_counter = $candidate.src_node_counter();
2919 let mut candidate_fees = $candidate.fees();
2920 if src_node_counter == payer_node_counter {
2921 candidate_fees = RoutingFees {
2923 proportional_millionths: 0,
2924 base_msat: 0,
2925 };
2926 }
2927 let path_htlc_minimum_msat = compute_fees_saturating(curr_min, candidate_fees)
2928 .saturating_add(curr_min);
2929
2930 let dist_entry = &mut dist[src_node_counter as usize];
2931 let old_entry = if let Some(hop) = dist_entry {
2932 hop
2933 } else {
2934 *dist_entry = Some(PathBuildingHop {
2940 candidate: $candidate.clone(),
2941 fee_msat: 0,
2942 next_hops_fee_msat: u64::max_value(),
2943 hop_use_fee_msat: u64::max_value(),
2944 total_fee_msat: u64::max_value(),
2945 path_htlc_minimum_msat,
2946 path_penalty_msat: u64::max_value(),
2947 was_processed: false,
2948 is_first_hop_target: false,
2949 is_last_hop_target: false,
2950 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
2951 best_path_from_hop_selected: false,
2952 value_contribution_msat,
2953 });
2954 dist_entry.as_mut().unwrap()
2955 };
2956
2957 #[allow(unused_mut)] let mut should_process = !old_entry.was_processed;
2959 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
2960 {
2961 if !should_process { should_process = true; }
2964 }
2965
2966 if should_process {
2967 let mut hop_use_fee_msat = 0;
2968 let mut total_fee_msat: u64 = $next_hops_fee_msat;
2969
2970 if src_node_id != our_node_id {
2973 hop_use_fee_msat = compute_fees_saturating(amount_to_transfer_over_msat, candidate_fees);
2976 total_fee_msat = total_fee_msat.saturating_add(hop_use_fee_msat);
2977 }
2978
2979 if total_fee_msat > max_total_routing_fee_msat {
2981 if should_log_candidate {
2982 log_trace!(logger, "Ignoring {} with fee {total_fee_msat} due to exceeding max total routing fee limit {max_total_routing_fee_msat}.", LoggedCandidateHop(&$candidate));
2983
2984 if let Some(_) = first_hop_details {
2985 log_trace!(logger,
2986 "First hop candidate routing fee: {}. Limit: {}",
2987 total_fee_msat,
2988 max_total_routing_fee_msat,
2989 );
2990 }
2991 }
2992 num_ignored_total_fee_limit += 1;
2993 } else {
2994 let channel_usage = ChannelUsage {
2995 amount_msat: amount_to_transfer_over_msat,
2996 inflight_htlc_msat: used_liquidity_msat,
2997 effective_capacity,
2998 };
2999 let channel_penalty_msat =
3000 scorer.channel_penalty_msat($candidate,
3001 channel_usage,
3002 score_params);
3003 let path_penalty_msat = $next_hops_path_penalty_msat
3004 .saturating_add(channel_penalty_msat);
3005
3006 let old_fee_cost = cmp::max(old_entry.total_fee_msat, old_entry.path_htlc_minimum_msat)
3024 .saturating_add(old_entry.path_penalty_msat);
3025 let new_fee_cost = cmp::max(total_fee_msat, path_htlc_minimum_msat)
3026 .saturating_add(path_penalty_msat);
3027 let old_cost = if old_fee_cost != u64::MAX && old_entry.value_contribution_msat != 0 {
3035 ((old_fee_cost as u128) << 64) / old_entry.value_contribution_msat as u128
3036 } else {
3037 u128::MAX
3038 };
3039 let new_cost = if new_fee_cost != u64::MAX {
3040 ((new_fee_cost as u128) << 64) / value_contribution_msat as u128
3043 } else {
3044 u128::MAX
3045 };
3046
3047 if !old_entry.was_processed && new_cost < old_cost {
3048 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
3049 {
3050 assert!(!old_entry.best_path_from_hop_selected);
3051 assert!(hop_total_cltv_delta <= u16::MAX as u32);
3052 }
3053
3054 let new_graph_node = RouteGraphNode {
3055 node_counter: src_node_counter,
3056 score: new_cost,
3057 total_cltv_delta: hop_total_cltv_delta as u16,
3058 value_contribution_msat,
3059 path_length_to_node,
3060 };
3061 targets.push(new_graph_node);
3062 old_entry.next_hops_fee_msat = $next_hops_fee_msat;
3063 old_entry.hop_use_fee_msat = hop_use_fee_msat;
3064 old_entry.total_fee_msat = total_fee_msat;
3065 old_entry.candidate = $candidate.clone();
3066 old_entry.fee_msat = 0; old_entry.path_htlc_minimum_msat = path_htlc_minimum_msat;
3068 old_entry.path_penalty_msat = path_penalty_msat;
3069 old_entry.value_contribution_msat = value_contribution_msat;
3070 hop_contribution_amt_msat = Some(value_contribution_msat);
3071 } else if old_entry.was_processed && new_cost < old_cost {
3072 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
3073 {
3074 debug_assert!(path_htlc_minimum_msat < old_entry.path_htlc_minimum_msat);
3094 debug_assert!(
3095 value_contribution_msat + path_penalty_msat <
3096 old_entry.value_contribution_msat + old_entry.path_penalty_msat
3097 );
3098 }
3099 }
3100 }
3101 }
3102 } else {
3103 if should_log_candidate {
3104 log_trace!(logger,
3105 "Ignoring {} due to its htlc_minimum_msat limit.",
3106 LoggedCandidateHop(&$candidate));
3107
3108 if let Some(details) = first_hop_details {
3109 log_trace!(logger,
3110 "First hop candidate next_outbound_htlc_minimum_msat: {}",
3111 details.next_outbound_htlc_minimum_msat,
3112 );
3113 }
3114 }
3115 num_ignored_htlc_minimum_msat_limit += 1;
3116 }
3117 }
3118 }
3119 hop_contribution_amt_msat
3120 } }
3121 }
3122
3123 let default_node_features = default_node_features();
3124
3125 #[rustfmt::skip]
3131 macro_rules! add_entries_to_cheapest_to_target_node {
3132 ( $node_counter: expr, $node_id: expr, $next_hops_value_contribution: expr,
3133 $next_hops_cltv_delta: expr, $next_hops_path_length: expr ) => {
3134 let fee_to_target_msat;
3135 let next_hops_path_htlc_minimum_msat;
3136 let next_hops_path_penalty_msat;
3137 let (is_first_hop_target, is_last_hop_target);
3138 let skip_node = if let Some(elem) = &mut dist[$node_counter as usize] {
3139 let was_processed = elem.was_processed;
3140 elem.was_processed = true;
3141 fee_to_target_msat = elem.total_fee_msat;
3142 next_hops_path_htlc_minimum_msat = elem.path_htlc_minimum_msat;
3143 next_hops_path_penalty_msat = elem.path_penalty_msat;
3144 is_first_hop_target = elem.is_first_hop_target;
3145 is_last_hop_target = elem.is_last_hop_target;
3146 was_processed
3147 } else {
3148 debug_assert_eq!($node_id, maybe_dummy_payee_node_id);
3152
3153 fee_to_target_msat = 0;
3154 next_hops_path_htlc_minimum_msat = 0;
3155 next_hops_path_penalty_msat = 0;
3156 is_first_hop_target = false;
3157 is_last_hop_target = false;
3158 false
3159 };
3160
3161 if !skip_node {
3162 if is_last_hop_target {
3163 if let Some(candidates) = last_hop_candidates.get(&$node_counter) {
3164 for candidate in candidates {
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 if is_first_hop_target {
3173 if let Some((first_channels, peer_node_counter)) = first_hop_targets.get(&$node_id) {
3174 for details in first_channels {
3175 debug_assert_eq!(*peer_node_counter, $node_counter);
3176 let candidate = CandidateRouteHop::FirstHop(FirstHopCandidate {
3177 details, payer_node_id: &our_node_id, payer_node_counter,
3178 target_node_counter: $node_counter,
3179 });
3180 add_entry!(&candidate, fee_to_target_msat,
3181 $next_hops_value_contribution,
3182 next_hops_path_htlc_minimum_msat, next_hops_path_penalty_msat,
3183 $next_hops_cltv_delta, $next_hops_path_length);
3184 }
3185 }
3186 }
3187
3188 if let Some(node) = network_nodes.get(&$node_id) {
3189 let features = if let Some(node_info) = node.announcement_info.as_ref() {
3190 &node_info.features()
3191 } else {
3192 &default_node_features
3193 };
3194
3195 if !features.requires_unknown_bits() {
3196 for chan_id in node.channels.iter() {
3197 let chan = network_channels.get(chan_id).unwrap();
3198 if !chan.features.requires_unknown_bits() {
3199 if let Some((directed_channel, source)) = chan.as_directed_to(&$node_id) {
3200 if first_hops.is_none() || *source != our_node_id {
3201 if directed_channel.direction().enabled {
3202 let candidate = CandidateRouteHop::PublicHop(PublicHopCandidate {
3203 info: directed_channel,
3204 short_channel_id: *chan_id,
3205 });
3206 add_entry!(&candidate,
3207 fee_to_target_msat,
3208 $next_hops_value_contribution,
3209 next_hops_path_htlc_minimum_msat,
3210 next_hops_path_penalty_msat,
3211 $next_hops_cltv_delta, $next_hops_path_length);
3212 }
3213 }
3214 }
3215 }
3216 }
3217 }
3218 }
3219 }
3220 };
3221 }
3222
3223 let mut payment_paths = Vec::<PaymentPath>::new();
3224
3225 'paths_collection: loop {
3227 targets.clear();
3230 for e in dist.iter_mut() {
3231 *e = None;
3232 }
3233
3234 for (_, (chans, peer_node_counter)) in first_hop_targets.iter() {
3244 dist[*peer_node_counter as usize] = Some(PathBuildingHop {
3251 candidate: CandidateRouteHop::FirstHop(FirstHopCandidate {
3252 details: &chans[0],
3253 payer_node_id: &our_node_id,
3254 target_node_counter: u32::max_value(),
3255 payer_node_counter: u32::max_value(),
3256 }),
3257 fee_msat: 0,
3258 next_hops_fee_msat: u64::max_value(),
3259 hop_use_fee_msat: u64::max_value(),
3260 total_fee_msat: u64::max_value(),
3261 path_htlc_minimum_msat: u64::max_value(),
3262 path_penalty_msat: u64::max_value(),
3263 was_processed: false,
3264 is_first_hop_target: true,
3265 is_last_hop_target: false,
3266 value_contribution_msat: 0,
3267 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
3268 best_path_from_hop_selected: false,
3269 });
3270 }
3271 for (target_node_counter, candidates) in last_hop_candidates.iter() {
3272 debug_assert!(!candidates.is_empty());
3279 if candidates.is_empty() { continue }
3280 let entry = &mut dist[**target_node_counter as usize];
3281 if let Some(hop) = entry {
3282 hop.is_last_hop_target = true;
3283 } else {
3284 *entry = Some(PathBuildingHop {
3285 candidate: candidates[0].clone(),
3286 fee_msat: 0,
3287 next_hops_fee_msat: u64::max_value(),
3288 hop_use_fee_msat: u64::max_value(),
3289 total_fee_msat: u64::max_value(),
3290 path_htlc_minimum_msat: u64::max_value(),
3291 path_penalty_msat: u64::max_value(),
3292 was_processed: false,
3293 is_first_hop_target: false,
3294 is_last_hop_target: true,
3295 value_contribution_msat: 0,
3296 #[cfg(all(not(ldk_bench), any(test, fuzzing)))]
3297 best_path_from_hop_selected: false,
3298 });
3299 }
3300 }
3301 hit_minimum_limit = false;
3302
3303 if let Some(payee) = payee_node_id_opt {
3304 if let Some(entry) = &mut dist[payee_node_counter as usize] {
3305 entry.next_hops_fee_msat = 0;
3308 entry.hop_use_fee_msat = 0;
3309 entry.total_fee_msat = 0;
3310 entry.path_htlc_minimum_msat = 0;
3311 entry.path_penalty_msat = 0;
3312 entry.value_contribution_msat = path_value_msat;
3313 }
3314 add_entries_to_cheapest_to_target_node!(
3315 payee_node_counter, payee, path_value_msat, 0, 0
3316 );
3317 }
3318
3319 debug_assert_eq!(
3320 payment_params.payee.blinded_route_hints().len(),
3321 introduction_node_id_cache.len(),
3322 "introduction_node_id_cache was built by iterating the blinded_route_hints, so they should be the same len"
3323 );
3324 let mut blind_intros_added = hash_map_with_capacity(payment_params.payee.blinded_route_hints().len());
3325 for (hint_idx, hint) in payment_params.payee.blinded_route_hints().iter().enumerate() {
3326 let source_node_opt = introduction_node_id_cache[hint_idx];
3330 let (source_node_id, source_node_counter) = if let Some(v) = source_node_opt { v } else { continue };
3331 if our_node_id == *source_node_id { continue }
3332 let candidate = if hint.blinded_hops().len() == 1 {
3333 CandidateRouteHop::OneHopBlinded(
3334 OneHopBlindedPathCandidate { source_node_counter, source_node_id, hint, hint_idx }
3335 )
3336 } else {
3337 CandidateRouteHop::Blinded(BlindedPathCandidate { source_node_counter, source_node_id, hint, hint_idx })
3338 };
3339 if let Some(hop_used_msat) = add_entry!(&candidate,
3340 0, path_value_msat, 0, 0_u64, 0, 0)
3341 {
3342 blind_intros_added.insert(source_node_id, (hop_used_msat, candidate));
3343 } else { continue }
3344 }
3345 for (source_node_id, (path_contribution_msat, candidate)) in blind_intros_added {
3354 if let Some((first_channels, peer_node_counter)) = first_hop_targets.get_mut(source_node_id) {
3355 sort_first_hop_channels(
3356 first_channels, &used_liquidities, recommended_value_msat, our_node_pubkey
3357 );
3358 for details in first_channels {
3359 let first_hop_candidate = CandidateRouteHop::FirstHop(FirstHopCandidate {
3360 details, payer_node_id: &our_node_id, payer_node_counter,
3361 target_node_counter: *peer_node_counter,
3362 });
3363 let blinded_path_fee = match compute_fees(path_contribution_msat, candidate.fees()) {
3364 Some(fee) => fee,
3365 None => continue
3366 };
3367 let path_min = candidate.htlc_minimum_msat().saturating_add(
3368 compute_fees_saturating(candidate.htlc_minimum_msat(), candidate.fees()));
3369 add_entry!(&first_hop_candidate, blinded_path_fee, path_contribution_msat, path_min,
3370 0_u64, candidate.cltv_expiry_delta(), 0);
3371 }
3372 }
3373 }
3374
3375 log_trace!(logger, "Starting main path collection loop with {} nodes pre-filled from first/last hops.", targets.len());
3376
3377 let mut found_new_path = false;
3380
3381 'path_construction: while let Some(RouteGraphNode { node_counter, total_cltv_delta, mut value_contribution_msat, path_length_to_node, .. }) = targets.pop() {
3391
3392 if node_counter == payer_node_counter {
3395 let mut new_entry = dist[payer_node_counter as usize].take().unwrap();
3396 let mut ordered_hops: Vec<(PathBuildingHop, NodeFeatures)> = vec!((new_entry.clone(), default_node_features.clone()));
3397
3398 'path_walk: loop {
3399 let mut features_set = false;
3400 let candidate = &ordered_hops.last().unwrap().0.candidate;
3401 let target = candidate.target().unwrap_or(maybe_dummy_payee_node_id);
3402 let target_node_counter = candidate.target_node_counter();
3403 if let Some((first_channels, _)) = first_hop_targets.get(&target) {
3404 for details in first_channels {
3405 if let CandidateRouteHop::FirstHop(FirstHopCandidate { details: last_hop_details, .. })
3406 = candidate
3407 {
3408 if details.get_outbound_payment_scid() == last_hop_details.get_outbound_payment_scid() {
3409 ordered_hops.last_mut().unwrap().1 = details.counterparty.features.to_context();
3410 features_set = true;
3411 break;
3412 }
3413 }
3414 }
3415 }
3416 if !features_set {
3417 if let Some(node) = network_nodes.get(&target) {
3418 if let Some(node_info) = node.announcement_info.as_ref() {
3419 ordered_hops.last_mut().unwrap().1 = node_info.features().clone();
3420 } else {
3421 ordered_hops.last_mut().unwrap().1 = default_node_features.clone();
3422 }
3423 } else {
3424 }
3428 }
3429
3430 if target_node_counter.is_none() {
3435 break 'path_walk;
3436 }
3437 if target_node_counter == Some(payee_node_counter) { break 'path_walk; }
3438
3439 new_entry = match dist[target_node_counter.unwrap() as usize].take() {
3440 Some(payment_hop) => payment_hop,
3441 None => unreachable!(),
3444 };
3445 ordered_hops.last_mut().unwrap().0.fee_msat = new_entry.hop_use_fee_msat;
3449 ordered_hops.push((new_entry.clone(), default_node_features.clone()));
3450 }
3451 ordered_hops.last_mut().unwrap().0.fee_msat = value_contribution_msat;
3452 ordered_hops.last_mut().unwrap().0.hop_use_fee_msat = 0;
3453
3454 log_trace!(logger, "Found a path back to us from the target with {} hops contributing up to {} msat: \n {:#?}",
3455 ordered_hops.len(), value_contribution_msat, ordered_hops.iter().map(|h| &(h.0)).collect::<Vec<&PathBuildingHop>>());
3456
3457 let mut payment_path = PaymentPath {hops: ordered_hops};
3458
3459 debug_assert_eq!(payment_path.get_value_msat(), value_contribution_msat);
3465 let (lowest_value_contrib_hop, max_path_contribution_msat) =
3466 match payment_path.max_final_value_msat(&used_liquidities, channel_saturation_pow_half) {
3467 Ok(contribution) => contribution,
3468 Err(candidate_idx_to_skip) => {
3469 let candidate = &payment_path.hops[candidate_idx_to_skip].0.candidate;
3470 log_trace!(logger,
3471 "Ignoring path because aggregate fees including hop {} overflow.",
3472 LoggedCandidateHop(candidate));
3473 mark_candidate_liquidity_exhausted(&mut used_liquidities, candidate);
3474 continue 'paths_collection;
3475 }
3476 };
3477 let desired_value_contribution = cmp::min(max_path_contribution_msat, final_value_msat);
3478 value_contribution_msat = payment_path.update_value_and_recompute_fees(desired_value_contribution);
3479
3480 for (hop, _) in payment_path.hops.iter() {
3490 let spent_on_hop_msat = value_contribution_msat + hop.next_hops_fee_msat;
3491 let used_liquidity_msat = used_liquidities
3492 .entry(hop.candidate.id())
3493 .and_modify(|used_liquidity_msat| *used_liquidity_msat += spent_on_hop_msat)
3494 .or_insert(spent_on_hop_msat);
3495 let hop_capacity = hop.candidate.effective_capacity();
3496 let hop_max_msat = max_htlc_from_capacity(hop_capacity, channel_saturation_pow_half);
3497 debug_assert!(*used_liquidity_msat <= hop_max_msat);
3498 }
3499 if max_path_contribution_msat > value_contribution_msat {
3500 let victim_candidate = &payment_path.hops[(payment_path.hops.len()) / 2].0.candidate;
3504 let exhausted = u64::max_value();
3505 log_trace!(logger,
3506 "Disabling route candidate {} for future path building iterations to avoid duplicates.",
3507 LoggedCandidateHop(victim_candidate));
3508 if let Some(scid) = victim_candidate.short_channel_id() {
3509 *used_liquidities.entry(CandidateHopId::Clear((scid, false))).or_default() = exhausted;
3510 *used_liquidities.entry(CandidateHopId::Clear((scid, true))).or_default() = exhausted;
3511 }
3512 } else {
3513 log_trace!(logger, "Path was limited to {}msat by hop {}", max_path_contribution_msat, lowest_value_contrib_hop);
3514 }
3515
3516 already_collected_value_msat += value_contribution_msat;
3519
3520 payment_paths.push(payment_path);
3521 found_new_path = true;
3522 break 'path_construction;
3523 }
3524
3525 if node_counter == payee_node_counter { continue 'path_construction; }
3529
3530 let node_id = if let Some(entry) = &dist[node_counter as usize] {
3531 entry.candidate.source()
3532 } else {
3533 debug_assert!(false, "Best nodes in the heap should have entries in dist");
3534 continue 'path_construction;
3535 };
3536
3537 add_entries_to_cheapest_to_target_node!(
3541 node_counter, node_id,
3542 value_contribution_msat,
3543 total_cltv_delta, path_length_to_node
3544 );
3545 }
3546
3547 if !allow_mpp {
3548 if !found_new_path && channel_saturation_pow_half != 0 {
3549 channel_saturation_pow_half = 0;
3550 continue 'paths_collection;
3551 }
3552 break 'paths_collection;
3554 }
3555
3556 if !found_new_path && channel_saturation_pow_half != 0 {
3562 channel_saturation_pow_half = 0;
3563 } else if !found_new_path && hit_minimum_limit && already_collected_value_msat < final_value_msat && path_value_msat != recommended_value_msat {
3564 log_trace!(logger, "Failed to collect enough value, but running again to collect extra paths with a potentially higher limit.");
3565 path_value_msat = recommended_value_msat;
3566 } else if already_collected_value_msat >= recommended_value_msat || !found_new_path {
3567 log_trace!(logger, "Have now collected {} msat (seeking {} msat) in paths. Last path loop {} a new path.",
3568 already_collected_value_msat, recommended_value_msat, if found_new_path { "found" } else { "did not find" });
3569 break 'paths_collection;
3570 } else if found_new_path && already_collected_value_msat == final_value_msat && payment_paths.len() == 1 {
3571 if !hit_minimum_limit {
3577 log_trace!(logger, "Collected exactly our payment amount on the first pass, without hitting an htlc_minimum_msat limit, exiting.");
3578 break 'paths_collection;
3579 }
3580 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.");
3581 path_value_msat = recommended_value_msat;
3582 }
3583 }
3584
3585 let num_ignored_total = num_ignored_value_contribution + num_ignored_path_length_limit +
3586 num_ignored_cltv_delta_limit + num_ignored_previously_failed +
3587 num_ignored_avoid_overpayment + num_ignored_htlc_minimum_msat_limit +
3588 num_ignored_total_fee_limit;
3589 if num_ignored_total > 0 {
3590 log_trace!(logger,
3591 "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.",
3592 num_ignored_value_contribution, num_ignored_path_length_limit,
3593 num_ignored_cltv_delta_limit, num_ignored_previously_failed,
3594 num_ignored_htlc_minimum_msat_limit, num_ignored_avoid_overpayment,
3595 num_ignored_total_fee_limit, num_ignored_total);
3596 }
3597
3598 if payment_paths.len() == 0 {
3600 return Err("Failed to find a path to the given destination");
3601 }
3602
3603 if already_collected_value_msat < final_value_msat {
3604 return Err("Failed to find a sufficient route to the given destination");
3605 }
3606
3607 let mut selected_route = payment_paths;
3609
3610 debug_assert_eq!(selected_route.iter().map(|p| p.get_value_msat()).sum::<u64>(), already_collected_value_msat);
3611 let mut overpaid_value_msat = already_collected_value_msat - final_value_msat;
3612
3613 selected_route.sort_unstable_by(|a, b| b.get_cost_per_msat().cmp(&a.get_cost_per_msat()));
3617
3618 let mut paths_left = selected_route.len();
3620 selected_route.retain(|path| {
3621 if paths_left == 1 {
3622 return true
3623 }
3624 let path_value_msat = path.get_value_msat();
3625 if path_value_msat <= overpaid_value_msat {
3626 overpaid_value_msat -= path_value_msat;
3627 paths_left -= 1;
3628 return false;
3629 }
3630 true
3631 });
3632 debug_assert!(selected_route.len() > 0);
3633
3634 if overpaid_value_msat != 0 {
3635 selected_route.sort_unstable_by(|a, b| {
3640 let a_f = a.hops.iter().map(|hop| hop.0.candidate.fees().proportional_millionths as u64).sum::<u64>();
3641 let b_f = b.hops.iter().map(|hop| hop.0.candidate.fees().proportional_millionths as u64).sum::<u64>();
3642 a_f.cmp(&b_f).then_with(|| b.get_cost_msat().cmp(&a.get_cost_msat()))
3643 });
3644 let expensive_payment_path = selected_route.first_mut().unwrap();
3645
3646 let expensive_path_new_value_msat = expensive_payment_path.get_value_msat() - overpaid_value_msat;
3649 expensive_payment_path.update_value_and_recompute_fees(expensive_path_new_value_msat);
3650 }
3651
3652 selected_route.sort_unstable_by_key(|path| {
3658 let mut key = [CandidateHopId::Clear((42, true)) ; MAX_PATH_LENGTH_ESTIMATE as usize];
3659 debug_assert!(path.hops.len() <= key.len());
3660 for (scid, key) in path.hops.iter() .map(|h| h.0.candidate.id()).zip(key.iter_mut()) {
3661 *key = scid;
3662 }
3663 key
3664 });
3665 for idx in 0..(selected_route.len() - 1) {
3666 if idx + 1 >= selected_route.len() { break; }
3667 if iter_equal(selected_route[idx ].hops.iter().map(|h| (h.0.candidate.id(), h.0.candidate.target())),
3668 selected_route[idx + 1].hops.iter().map(|h| (h.0.candidate.id(), h.0.candidate.target()))) {
3669 let new_value = selected_route[idx].get_value_msat() + selected_route[idx + 1].get_value_msat();
3670 selected_route[idx].update_value_and_recompute_fees(new_value);
3671 selected_route.remove(idx + 1);
3672 }
3673 }
3674
3675 let mut paths = Vec::new();
3676 for payment_path in selected_route {
3677 let mut hops = Vec::with_capacity(payment_path.hops.len());
3678 for (hop, node_features) in payment_path.hops.iter()
3679 .filter(|(h, _)| h.candidate.short_channel_id().is_some())
3680 {
3681 let target = hop.candidate.target().expect("target is defined when short_channel_id is defined");
3682 let maybe_announced_channel = if let CandidateRouteHop::PublicHop(_) = hop.candidate {
3683 true
3685 } else if let CandidateRouteHop::FirstHop(first_hop) = &hop.candidate {
3686 first_hop.details.is_announced
3688 } else {
3689 network_graph.node(&target).map_or(false, |hop_node|
3694 hop_node.channels.iter().any(|scid| network_graph.channel(*scid)
3695 .map_or(false, |c| c.as_directed_from(&hop.candidate.source()).is_some()))
3696 )
3697 };
3698
3699 hops.push(RouteHop {
3700 pubkey: PublicKey::from_slice(target.as_slice()).map_err(|_| "A PublicKey in NetworkGraph is invalid!")?,
3701 node_features: node_features.clone(),
3702 short_channel_id: hop.candidate.short_channel_id().unwrap(),
3703 channel_features: hop.candidate.features(),
3704 fee_msat: hop.fee_msat,
3705 cltv_expiry_delta: hop.candidate.cltv_expiry_delta(),
3706 maybe_announced_channel,
3707 });
3708 }
3709 let mut final_cltv_delta = final_cltv_expiry_delta;
3710 let blinded_tail = payment_path.hops.last().and_then(|(h, _)| {
3711 if let Some(blinded_path) = h.candidate.blinded_path() {
3712 final_cltv_delta = h.candidate.cltv_expiry_delta();
3713 Some(BlindedTail {
3714 trampoline_hops: vec![],
3716 hops: blinded_path.blinded_hops().to_vec(),
3717 blinding_point: blinded_path.blinding_point(),
3718 excess_final_cltv_expiry_delta: 0,
3719 final_value_msat: h.fee_msat,
3720 })
3721 } else { None }
3722 });
3723 hops.iter_mut().rev().fold(final_cltv_delta, |prev_cltv_expiry_delta, hop| {
3726 core::mem::replace(&mut hop.cltv_expiry_delta, prev_cltv_expiry_delta)
3727 });
3728
3729 paths.push(Path { hops, blinded_tail });
3730 }
3731 debug_assert!(paths.len() <= payment_params.max_path_count.into());
3733
3734 if let Some(node_features) = payment_params.payee.node_features() {
3735 for path in paths.iter_mut() {
3736 path.hops.last_mut().unwrap().node_features = node_features.clone();
3737 }
3738 }
3739
3740 let route = Route { paths, route_params: Some(route_params.clone()) };
3741
3742 if let Some(max_total_routing_fee_msat) = route_params.max_total_routing_fee_msat {
3744 if route.get_total_fees() > max_total_routing_fee_msat {
3745 return Err("Failed to find route that adheres to the maximum total fee limit");
3746 }
3747 }
3748
3749 log_info!(logger, "Got route: {}", log_route!(route));
3750 Ok(route)
3751}
3752
3753#[rustfmt::skip]
3758fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters,
3759 network_graph: &ReadOnlyNetworkGraph, random_seed_bytes: &[u8; 32]
3760) {
3761 let network_channels = network_graph.channels();
3762 let network_nodes = network_graph.nodes();
3763
3764 for path in route.paths.iter_mut() {
3765 let mut shadow_ctlv_expiry_delta_offset: u32 = 0;
3766
3767 let mut nodes_to_avoid: [NodeId; 3] = [NodeId::from_pubkey(&path.hops.last().unwrap().pubkey),
3770 NodeId::from_pubkey(&path.hops.get(path.hops.len().saturating_sub(2)).unwrap().pubkey),
3771 NodeId::from_pubkey(&path.hops.get(path.hops.len().saturating_sub(3)).unwrap().pubkey)];
3772
3773 let mut cur_hop: Option<NodeId> = None;
3775 let mut path_nonce = [0u8; 12];
3776 if let Some(starting_hop) = path.hops.iter().rev()
3777 .find(|h| network_nodes.contains_key(&NodeId::from_pubkey(&h.pubkey))) {
3778 cur_hop = Some(NodeId::from_pubkey(&starting_hop.pubkey));
3779 path_nonce.copy_from_slice(&cur_hop.unwrap().as_slice()[..12]);
3780 }
3781
3782 let mut prng = ChaCha20::new(random_seed_bytes, &path_nonce);
3784 let mut random_path_bytes = [0u8; ::core::mem::size_of::<usize>()];
3785
3786 prng.process_in_place(&mut random_path_bytes);
3788 let random_walk_length = usize::from_be_bytes(random_path_bytes).wrapping_rem(3).wrapping_add(1);
3789
3790 for random_hop in 0..random_walk_length {
3791 let mut random_hop_offset = MEDIAN_HOP_CLTV_EXPIRY_DELTA;
3794
3795 if let Some(cur_node_id) = cur_hop {
3796 if let Some(cur_node) = network_nodes.get(&cur_node_id) {
3797 prng.process_in_place(&mut random_path_bytes);
3799 if let Some(random_channel) = usize::from_be_bytes(random_path_bytes)
3800 .checked_rem(cur_node.channels.len())
3801 .and_then(|index| cur_node.channels.get(index))
3802 .and_then(|id| network_channels.get(id)) {
3803 random_channel.as_directed_from(&cur_node_id).map(|(dir_info, next_id)| {
3804 if !nodes_to_avoid.iter().any(|x| x == next_id) {
3805 nodes_to_avoid[random_hop] = *next_id;
3806 random_hop_offset = dir_info.direction().cltv_expiry_delta.into();
3807 cur_hop = Some(*next_id);
3808 }
3809 });
3810 }
3811 }
3812 }
3813
3814 shadow_ctlv_expiry_delta_offset = shadow_ctlv_expiry_delta_offset
3815 .checked_add(random_hop_offset)
3816 .unwrap_or(shadow_ctlv_expiry_delta_offset);
3817 }
3818
3819 const MAX_SHADOW_CLTV_EXPIRY_DELTA_OFFSET: u32 = 3*144;
3821 shadow_ctlv_expiry_delta_offset = cmp::min(shadow_ctlv_expiry_delta_offset, MAX_SHADOW_CLTV_EXPIRY_DELTA_OFFSET);
3822
3823 let path_total_cltv_expiry_delta: u32 = path.hops.iter().map(|h| h.cltv_expiry_delta).sum();
3826 let mut max_path_offset = payment_params.max_total_cltv_expiry_delta - path_total_cltv_expiry_delta;
3827 max_path_offset = cmp::max(
3828 max_path_offset - (max_path_offset % MEDIAN_HOP_CLTV_EXPIRY_DELTA),
3829 max_path_offset % MEDIAN_HOP_CLTV_EXPIRY_DELTA);
3830 shadow_ctlv_expiry_delta_offset = cmp::min(shadow_ctlv_expiry_delta_offset, max_path_offset);
3831
3832 if let Some(tail) = path.blinded_tail.as_mut() {
3834 tail.excess_final_cltv_expiry_delta = tail.excess_final_cltv_expiry_delta
3835 .checked_add(shadow_ctlv_expiry_delta_offset).unwrap_or(tail.excess_final_cltv_expiry_delta);
3836 }
3837 if let Some(last_hop) = path.hops.last_mut() {
3838 last_hop.cltv_expiry_delta = last_hop.cltv_expiry_delta
3839 .checked_add(shadow_ctlv_expiry_delta_offset).unwrap_or(last_hop.cltv_expiry_delta);
3840 }
3841 }
3842}
3843
3844#[rustfmt::skip]
3849pub fn build_route_from_hops<L: Deref, GL: Deref>(
3850 our_node_pubkey: &PublicKey, hops: &[PublicKey], route_params: &RouteParameters,
3851 network_graph: &NetworkGraph<GL>, logger: L, random_seed_bytes: &[u8; 32]
3852) -> Result<Route, &'static str>
3853where L::Target: Logger, GL::Target: Logger {
3854 let graph_lock = network_graph.read_only();
3855 let mut route = build_route_from_hops_internal(our_node_pubkey, hops, &route_params,
3856 &graph_lock, logger, random_seed_bytes)?;
3857 add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes);
3858 Ok(route)
3859}
3860
3861#[rustfmt::skip]
3862fn build_route_from_hops_internal<L: Deref>(
3863 our_node_pubkey: &PublicKey, hops: &[PublicKey], route_params: &RouteParameters,
3864 network_graph: &ReadOnlyNetworkGraph, logger: L, random_seed_bytes: &[u8; 32],
3865) -> Result<Route, &'static str> where L::Target: Logger {
3866
3867 struct HopScorer {
3868 our_node_id: NodeId,
3869 hop_ids: [Option<NodeId>; MAX_PATH_LENGTH_ESTIMATE as usize],
3870 }
3871
3872 impl ScoreLookUp for HopScorer {
3873 type ScoreParams = ();
3874 fn channel_penalty_msat(&self, candidate: &CandidateRouteHop,
3875 _usage: ChannelUsage, _score_params: &Self::ScoreParams) -> u64
3876 {
3877 let mut cur_id = self.our_node_id;
3878 for i in 0..self.hop_ids.len() {
3879 if let Some(next_id) = self.hop_ids[i] {
3880 if cur_id == candidate.source() && Some(next_id) == candidate.target() {
3881 return 0;
3882 }
3883 cur_id = next_id;
3884 } else {
3885 break;
3886 }
3887 }
3888 u64::max_value()
3889 }
3890 }
3891
3892 impl<'a> Writeable for HopScorer {
3893 #[inline]
3894 #[rustfmt::skip]
3895 fn write<W: Writer>(&self, _w: &mut W) -> Result<(), io::Error> {
3896 unreachable!();
3897 }
3898 }
3899
3900 if hops.len() > MAX_PATH_LENGTH_ESTIMATE.into() {
3901 return Err("Cannot build a route exceeding the maximum path length.");
3902 }
3903
3904 let our_node_id = NodeId::from_pubkey(our_node_pubkey);
3905 let mut hop_ids = [None; MAX_PATH_LENGTH_ESTIMATE as usize];
3906 for i in 0..hops.len() {
3907 hop_ids[i] = Some(NodeId::from_pubkey(&hops[i]));
3908 }
3909
3910 let scorer = HopScorer { our_node_id, hop_ids };
3911
3912 get_route(our_node_pubkey, route_params, network_graph, None, logger, &scorer, &Default::default(), random_seed_bytes)
3913}
3914
3915#[cfg(test)]
3916mod tests {
3917 use crate::blinded_path::payment::{BlindedPayInfo, BlindedPaymentPath};
3918 use crate::blinded_path::BlindedHop;
3919 use crate::chain::transaction::OutPoint;
3920 use crate::crypto::chacha20::ChaCha20;
3921 use crate::ln::chan_utils::make_funding_redeemscript;
3922 use crate::ln::channel_state::{ChannelCounterparty, ChannelDetails, ChannelShutdownState};
3923 use crate::ln::channelmanager;
3924 use crate::ln::msgs::{UnsignedChannelUpdate, MAX_VALUE_MSAT};
3925 use crate::ln::types::ChannelId;
3926 use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId, P2PGossipSync};
3927 use crate::routing::router::{
3928 add_random_cltv_offset, build_route_from_hops_internal, default_node_features, get_route,
3929 BlindedTail, CandidateRouteHop, InFlightHtlcs, Path, PaymentParameters, PublicHopCandidate,
3930 Route, RouteHint, RouteHintHop, RouteHop, RouteParameters, RoutingFees,
3931 DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE,
3932 };
3933 use crate::routing::scoring::{
3934 ChannelUsage, FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringDecayParameters,
3935 ProbabilisticScoringFeeParameters, ScoreLookUp,
3936 };
3937 use crate::routing::test_utils::{
3938 add_channel, add_or_update_node, build_graph, build_line_graph, get_nodes,
3939 id_to_feature_flags, update_channel,
3940 };
3941 use crate::routing::utxo::UtxoResult;
3942 use crate::types::features::{BlindedHopFeatures, ChannelFeatures, InitFeatures, NodeFeatures};
3943 use crate::util::config::UserConfig;
3944 #[cfg(c_bindings)]
3945 use crate::util::ser::Writer;
3946 use crate::util::ser::{FixedLengthReader, Readable, ReadableArgs, Writeable};
3947 use crate::util::test_utils as ln_test_utils;
3948
3949 use bitcoin::amount::Amount;
3950 use bitcoin::bech32::primitives::decode::CheckedHrpstring;
3951 use bitcoin::bech32::{ByteIterExt, Fe32IterExt};
3952 use bitcoin::constants::ChainHash;
3953 use bitcoin::hashes::{sha256::Hash as Sha256, Hash};
3954 use bitcoin::hex::FromHex;
3955 use bitcoin::network::Network;
3956 use bitcoin::opcodes;
3957 use bitcoin::script::Builder;
3958 use bitcoin::secp256k1::Secp256k1;
3959 use bitcoin::secp256k1::{PublicKey, SecretKey};
3960 use bitcoin::transaction::TxOut;
3961
3962 use lightning_invoice::{Bolt11Bech32, Bolt11Invoice, Currency, InvoiceBuilder};
3963
3964 use crate::io::Cursor;
3965 use crate::prelude::*;
3966 use crate::sync::Arc;
3967 use crate::types::payment::PaymentSecret;
3968
3969 fn invoice_with_included_payee_pub_key_and_bad_recovery_id() -> (Bolt11Invoice, PublicKey) {
3970 let secp_ctx = Secp256k1::new();
3971 let private_key = SecretKey::from_slice(&[42; 32]).unwrap();
3972 let public_key = PublicKey::from_secret_key(&secp_ctx, &private_key);
3973
3974 let invoice = InvoiceBuilder::new(Currency::Bitcoin)
3975 .description("Test".to_string())
3976 .amount_milli_satoshis(1000)
3977 .payment_hash(Sha256::from_slice(&[0; 32][..]).unwrap())
3978 .payment_secret(PaymentSecret([21; 32]))
3979 .payee_pub_key(public_key)
3980 .min_final_cltv_expiry_delta(144)
3981 .duration_since_epoch(core::time::Duration::from_secs(1234567))
3982 .build_signed(|hash| secp_ctx.sign_ecdsa_recoverable(hash, &private_key))
3983 .unwrap();
3984
3985 let invoice_string = invoice.to_string();
3986 let parsed = CheckedHrpstring::new::<Bolt11Bech32>(&invoice_string).unwrap();
3987 let hrp = parsed.hrp();
3988 let mut data: Vec<_> = parsed.fe32_iter::<&mut dyn Iterator<Item = u8>>().collect();
3989 let signature_start = data.len() - 104;
3990 let mut signature_bytes: Vec<u8> =
3991 data[signature_start..].iter().copied().fes_to_bytes().collect();
3992 signature_bytes[64] = 2;
3993 let signature_data: Vec<_> = signature_bytes.into_iter().bytes_to_fes().collect();
3994 data.splice(signature_start.., signature_data);
3995
3996 let bad_invoice_string = data
3997 .into_iter()
3998 .with_checksum::<bitcoin::bech32::Bech32>(&hrp)
3999 .chars()
4000 .collect::<String>();
4001 (bad_invoice_string.parse().unwrap(), public_key)
4002 }
4003
4004 #[test]
4005 fn payment_params_from_bolt11_invoice_uses_included_payee_pub_key() {
4006 let (invoice, public_key) = invoice_with_included_payee_pub_key_and_bad_recovery_id();
4007 let payment_params = PaymentParameters::from_bolt11_invoice(&invoice);
4008
4009 match payment_params.payee {
4010 super::Payee::Clear { node_id, .. } => assert_eq!(node_id, public_key),
4011 super::Payee::Blinded { .. } => panic!("BOLT11 invoice should create a clear payee"),
4012 }
4013 }
4014
4015 #[rustfmt::skip]
4016 fn get_channel_details(short_channel_id: Option<u64>, node_id: PublicKey,
4017 features: InitFeatures, outbound_capacity_msat: u64) -> ChannelDetails {
4018 #[allow(deprecated)] ChannelDetails {
4020 channel_id: ChannelId::new_zero(),
4021 counterparty: ChannelCounterparty {
4022 features,
4023 node_id,
4024 unspendable_punishment_reserve: 0,
4025 forwarding_info: None,
4026 outbound_htlc_minimum_msat: None,
4027 outbound_htlc_maximum_msat: None,
4028 },
4029 funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
4030 funding_redeem_script: Some(make_funding_redeemscript(
4031 &PublicKey::from_slice(&[2; 33]).unwrap(),
4032 &PublicKey::from_slice(&[2; 33]).unwrap(),
4033 )),
4034 channel_type: None,
4035 short_channel_id,
4036 outbound_scid_alias: None,
4037 inbound_scid_alias: None,
4038 channel_value_satoshis: 0,
4039 user_channel_id: 0,
4040 outbound_capacity_msat,
4041 next_outbound_htlc_limit_msat: outbound_capacity_msat,
4042 next_outbound_htlc_minimum_msat: 0,
4043 inbound_capacity_msat: 42,
4044 unspendable_punishment_reserve: None,
4045 confirmations_required: None,
4046 confirmations: None,
4047 force_close_spend_delay: None,
4048 is_outbound: true, is_channel_ready: true,
4049 is_usable: true, is_announced: true,
4050 inbound_htlc_minimum_msat: None,
4051 inbound_htlc_maximum_msat: None,
4052 config: None,
4053 feerate_sat_per_1000_weight: None,
4054 channel_shutdown_state: Some(ChannelShutdownState::NotShuttingDown),
4055 pending_inbound_htlcs: Vec::new(),
4056 pending_outbound_htlcs: Vec::new(),
4057 }
4058 }
4059
4060 #[rustfmt::skip]
4061 fn dummy_blinded_path(intro_node: PublicKey, payinfo: BlindedPayInfo) -> BlindedPaymentPath {
4062 BlindedPaymentPath::from_blinded_path_and_payinfo(
4063 intro_node, ln_test_utils::pubkey(42),
4064 vec![
4065 BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() },
4066 BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() }
4067 ],
4068 payinfo
4069 )
4070 }
4071
4072 #[rustfmt::skip]
4073 fn dummy_one_hop_blinded_path(intro_node: PublicKey, payinfo: BlindedPayInfo) -> BlindedPaymentPath {
4074 BlindedPaymentPath::from_blinded_path_and_payinfo(
4075 intro_node, ln_test_utils::pubkey(42),
4076 vec![
4077 BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() },
4078 ],
4079 payinfo
4080 )
4081 }
4082
4083 #[test]
4084 #[rustfmt::skip]
4085 fn simple_route_test() {
4086 let (secp_ctx, network_graph, _, _, logger) = build_graph();
4087 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
4088 let mut payment_params = PaymentParameters::from_node_id(nodes[2], 42);
4089 let scorer = ln_test_utils::TestScorer::new();
4090 let random_seed_bytes = [42; 32];
4091
4092 let route_params = RouteParameters::from_payment_params_and_value(
4095 payment_params.clone(), 0);
4096 if let Err(err) = get_route(&our_id,
4097 &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer,
4098 &Default::default(), &random_seed_bytes) {
4099 assert_eq!(err, "Cannot send a payment of 0 msat");
4100 } else { panic!(); }
4101
4102 payment_params.max_path_length = 2;
4103 let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4104 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4105 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4106 assert_eq!(route.paths[0].hops.len(), 2);
4107
4108 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
4109 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
4110 assert_eq!(route.paths[0].hops[0].fee_msat, 100);
4111 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
4112 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
4113 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
4114
4115 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
4116 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
4117 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
4118 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
4119 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4120 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
4121
4122 route_params.payment_params.max_path_length = 1;
4123 get_route(&our_id, &route_params, &network_graph.read_only(), None,
4124 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap_err();
4125 }
4126
4127 #[test]
4128 #[rustfmt::skip]
4129 fn invalid_first_hop_test() {
4130 let (secp_ctx, network_graph, _, _, logger) = build_graph();
4131 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
4132 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
4133 let scorer = ln_test_utils::TestScorer::new();
4134 let random_seed_bytes = [42; 32];
4135
4136 let our_chans = [get_channel_details(Some(2), our_id, InitFeatures::from_le_bytes(vec![0b11]), 100000)];
4139
4140 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4141 if let Err(err) = get_route(&our_id,
4142 &route_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()),
4143 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) {
4144 assert_eq!(err, "First hop cannot have our_node_pubkey as a destination.");
4145 } else { panic!(); }
4146
4147 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4148 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4149 assert_eq!(route.paths[0].hops.len(), 2);
4150 }
4151
4152 #[test]
4153 #[rustfmt::skip]
4154 fn htlc_minimum_test() {
4155 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
4156 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
4157 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
4158 let scorer = ln_test_utils::TestScorer::new();
4159 let random_seed_bytes = [42; 32];
4160
4161 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4165 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4166 short_channel_id: 12,
4167 timestamp: 2,
4168 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4171 htlc_minimum_msat: 0,
4172 htlc_maximum_msat: MAX_VALUE_MSAT,
4173 fee_base_msat: 0,
4174 fee_proportional_millionths: 0,
4175 excess_data: Vec::new()
4176 });
4177 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
4178 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4179 short_channel_id: 3,
4180 timestamp: 2,
4181 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4184 htlc_minimum_msat: 0,
4185 htlc_maximum_msat: MAX_VALUE_MSAT,
4186 fee_base_msat: 0,
4187 fee_proportional_millionths: 0,
4188 excess_data: Vec::new()
4189 });
4190 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
4191 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4192 short_channel_id: 13,
4193 timestamp: 2,
4194 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4197 htlc_minimum_msat: 0,
4198 htlc_maximum_msat: MAX_VALUE_MSAT,
4199 fee_base_msat: 0,
4200 fee_proportional_millionths: 0,
4201 excess_data: Vec::new()
4202 });
4203 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
4204 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4205 short_channel_id: 6,
4206 timestamp: 2,
4207 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4210 htlc_minimum_msat: 0,
4211 htlc_maximum_msat: MAX_VALUE_MSAT,
4212 fee_base_msat: 0,
4213 fee_proportional_millionths: 0,
4214 excess_data: Vec::new()
4215 });
4216 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
4217 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4218 short_channel_id: 7,
4219 timestamp: 2,
4220 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4223 htlc_minimum_msat: 0,
4224 htlc_maximum_msat: MAX_VALUE_MSAT,
4225 fee_base_msat: 0,
4226 fee_proportional_millionths: 0,
4227 excess_data: Vec::new()
4228 });
4229
4230 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4233 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4234 short_channel_id: 2,
4235 timestamp: 3,
4236 message_flags: 1, channel_flags: 0,
4238 cltv_expiry_delta: 0,
4239 htlc_minimum_msat: 200_000_000,
4240 htlc_maximum_msat: MAX_VALUE_MSAT,
4241 fee_base_msat: 0,
4242 fee_proportional_millionths: 0,
4243 excess_data: Vec::new()
4244 });
4245
4246 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
4249 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4250 short_channel_id: 4,
4251 timestamp: 3,
4252 message_flags: 1, channel_flags: 0,
4254 cltv_expiry_delta: 0,
4255 htlc_minimum_msat: 0,
4256 htlc_maximum_msat: 199_999_999,
4257 fee_base_msat: 0,
4258 fee_proportional_millionths: 0,
4259 excess_data: Vec::new()
4260 });
4261
4262 let route_params = RouteParameters::from_payment_params_and_value(
4264 payment_params, 199_999_999);
4265 if let Err(err) = get_route(&our_id,
4266 &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer,
4267 &Default::default(), &random_seed_bytes) {
4268 assert_eq!(err, "Failed to find a path to the given destination");
4269 } else { panic!(); }
4270
4271 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4273 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4274 short_channel_id: 2,
4275 timestamp: 4,
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 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4288 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4289 assert_eq!(route.paths[0].hops.len(), 2);
4290 }
4291
4292 #[test]
4293 #[rustfmt::skip]
4294 fn htlc_minimum_overpay_test() {
4295 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
4296 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
4297 let config = UserConfig::default();
4298 let payment_params = PaymentParameters::from_node_id(nodes[2], 42)
4299 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
4300 .unwrap();
4301 let scorer = ln_test_utils::TestScorer::new();
4302 let random_seed_bytes = [42; 32];
4303
4304 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4308 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4309 short_channel_id: 2,
4310 timestamp: 2,
4311 message_flags: 1, channel_flags: 0,
4313 cltv_expiry_delta: 0,
4314 htlc_minimum_msat: 35_000,
4315 htlc_maximum_msat: 40_000,
4316 fee_base_msat: 0,
4317 fee_proportional_millionths: 0,
4318 excess_data: Vec::new()
4319 });
4320 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4321 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4322 short_channel_id: 12,
4323 timestamp: 3,
4324 message_flags: 1, channel_flags: 0,
4326 cltv_expiry_delta: 0,
4327 htlc_minimum_msat: 35_000,
4328 htlc_maximum_msat: 40_000,
4329 fee_base_msat: 0,
4330 fee_proportional_millionths: 0,
4331 excess_data: Vec::new()
4332 });
4333
4334 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
4336 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4337 short_channel_id: 13,
4338 timestamp: 2,
4339 message_flags: 1, channel_flags: 0,
4341 cltv_expiry_delta: 0,
4342 htlc_minimum_msat: 0,
4343 htlc_maximum_msat: MAX_VALUE_MSAT,
4344 fee_base_msat: 0,
4345 fee_proportional_millionths: 0,
4346 excess_data: Vec::new()
4347 });
4348 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
4349 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4350 short_channel_id: 4,
4351 timestamp: 2,
4352 message_flags: 1, channel_flags: 0,
4354 cltv_expiry_delta: 0,
4355 htlc_minimum_msat: 0,
4356 htlc_maximum_msat: MAX_VALUE_MSAT,
4357 fee_base_msat: 0,
4358 fee_proportional_millionths: 0,
4359 excess_data: Vec::new()
4360 });
4361
4362 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4364 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4365 short_channel_id: 1,
4366 timestamp: 3,
4367 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4370 htlc_minimum_msat: 0,
4371 htlc_maximum_msat: MAX_VALUE_MSAT,
4372 fee_base_msat: 0,
4373 fee_proportional_millionths: 0,
4374 excess_data: Vec::new()
4375 });
4376
4377 let mut route_params = RouteParameters::from_payment_params_and_value(
4378 payment_params.clone(), 60_000);
4379 route_params.max_total_routing_fee_msat = Some(15_000);
4380 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4381 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4382 let overpaid_fees = route.paths[0].hops[0].fee_msat + route.paths[1].hops[0].fee_msat;
4384 assert_eq!(overpaid_fees, 15_000);
4386
4387 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4390 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4391 short_channel_id: 12,
4392 timestamp: 4,
4393 message_flags: 1, channel_flags: 0,
4395 cltv_expiry_delta: 0,
4396 htlc_minimum_msat: 65_000,
4397 htlc_maximum_msat: 80_000,
4398 fee_base_msat: 0,
4399 fee_proportional_millionths: 0,
4400 excess_data: Vec::new()
4401 });
4402 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4403 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4404 short_channel_id: 2,
4405 timestamp: 3,
4406 message_flags: 1, channel_flags: 0,
4408 cltv_expiry_delta: 0,
4409 htlc_minimum_msat: 0,
4410 htlc_maximum_msat: MAX_VALUE_MSAT,
4411 fee_base_msat: 0,
4412 fee_proportional_millionths: 0,
4413 excess_data: Vec::new()
4414 });
4415 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
4416 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4417 short_channel_id: 4,
4418 timestamp: 4,
4419 message_flags: 1, channel_flags: 0,
4421 cltv_expiry_delta: 0,
4422 htlc_minimum_msat: 0,
4423 htlc_maximum_msat: MAX_VALUE_MSAT,
4424 fee_base_msat: 0,
4425 fee_proportional_millionths: 100_000,
4426 excess_data: Vec::new()
4427 });
4428
4429 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4430 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4431 assert_eq!(route.paths.len(), 1);
4433 assert_eq!(route.paths[0].hops[0].short_channel_id, 12);
4434 let fees = route.paths[0].hops[0].fee_msat;
4435 assert_eq!(fees, 5_000);
4436
4437 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 50_000);
4438 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4439 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4440 assert_eq!(route.paths.len(), 1);
4443 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
4444 let fees = route.paths[0].hops[0].fee_msat;
4445 assert_eq!(fees, 5_000);
4446 }
4447
4448 #[test]
4449 #[rustfmt::skip]
4450 fn htlc_minimum_recipient_overpay_test() {
4451 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
4452 let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
4453 let config = UserConfig::default();
4454 let payment_params = PaymentParameters::from_node_id(nodes[2], 42).with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap();
4455 let scorer = ln_test_utils::TestScorer::new();
4456 let random_seed_bytes = [42; 32];
4457
4458 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
4462 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4463 short_channel_id: 13,
4464 timestamp: 2,
4465 message_flags: 1, channel_flags: 3,
4467 cltv_expiry_delta: 0,
4468 htlc_minimum_msat: 0,
4469 htlc_maximum_msat: 0,
4470 fee_base_msat: 0,
4471 fee_proportional_millionths: 0,
4472 excess_data: Vec::new()
4473 });
4474
4475 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
4477 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4478 short_channel_id: 4,
4479 timestamp: 2,
4480 message_flags: 1, channel_flags: 0,
4482 cltv_expiry_delta: 0,
4483 htlc_minimum_msat: 15_000,
4484 htlc_maximum_msat: MAX_VALUE_MSAT,
4485 fee_base_msat: 0,
4486 fee_proportional_millionths: 0,
4487 excess_data: Vec::new()
4488 });
4489
4490 let mut route_params = RouteParameters::from_payment_params_and_value(
4495 payment_params.clone(), 5_000);
4496 route_params.max_total_routing_fee_msat = Some(9_999);
4497 if let Err(err) = get_route(&our_id,
4498 &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer,
4499 &Default::default(), &random_seed_bytes) {
4500 assert_eq!(err, "Failed to find route that adheres to the maximum total fee limit");
4501 } else { panic!(); }
4502
4503 let mut route_params = RouteParameters::from_payment_params_and_value(
4504 payment_params.clone(), 5_000);
4505 route_params.max_total_routing_fee_msat = Some(10_000);
4506 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4507 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4508 assert_eq!(route.get_total_fees(), 10_000);
4509 }
4510
4511 #[test]
4512 #[rustfmt::skip]
4513 fn disable_channels_test() {
4514 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
4515 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
4516 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
4517 let scorer = ln_test_utils::TestScorer::new();
4518 let random_seed_bytes = [42; 32];
4519
4520 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
4522 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4523 short_channel_id: 4,
4524 timestamp: 2,
4525 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4528 htlc_minimum_msat: 0,
4529 htlc_maximum_msat: MAX_VALUE_MSAT,
4530 fee_base_msat: 0,
4531 fee_proportional_millionths: 0,
4532 excess_data: Vec::new()
4533 });
4534 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
4535 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4536 short_channel_id: 12,
4537 timestamp: 2,
4538 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4541 htlc_minimum_msat: 0,
4542 htlc_maximum_msat: MAX_VALUE_MSAT,
4543 fee_base_msat: 0,
4544 fee_proportional_millionths: 0,
4545 excess_data: Vec::new()
4546 });
4547
4548 let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4550 if let Err(err) = get_route(&our_id,
4551 &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer,
4552 &Default::default(), &random_seed_bytes) {
4553 assert_eq!(err, "Failed to find a path to the given destination");
4554 } else { panic!(); }
4555
4556 let our_chans = [get_channel_details(Some(42), nodes[7].clone(),
4558 InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
4559 route_params.payment_params.max_path_length = 2;
4560 let route = get_route(&our_id, &route_params, &network_graph.read_only(),
4561 Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
4562 &Default::default(), &random_seed_bytes).unwrap();
4563 assert_eq!(route.paths[0].hops.len(), 2);
4564
4565 assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
4566 assert_eq!(route.paths[0].hops[0].short_channel_id, 42);
4567 assert_eq!(route.paths[0].hops[0].fee_msat, 200);
4568 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (13 << 4) | 1);
4569 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]);
4573 assert_eq!(route.paths[0].hops[1].short_channel_id, 13);
4574 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
4575 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
4576 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4577 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(13));
4578 }
4579
4580 #[test]
4581 #[rustfmt::skip]
4582 fn disable_node_test() {
4583 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
4584 let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
4585 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
4586 let scorer = ln_test_utils::TestScorer::new();
4587 let random_seed_bytes = [42; 32];
4588
4589 let mut unknown_features = NodeFeatures::empty();
4591 unknown_features.set_unknown_feature_required();
4592 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[0], unknown_features.clone(), 1);
4593 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[1], unknown_features.clone(), 1);
4594 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[7], unknown_features.clone(), 1);
4595
4596 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4598 if let Err(err) = get_route(&our_id,
4599 &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer,
4600 &Default::default(), &random_seed_bytes) {
4601 assert_eq!(err, "Failed to find a path to the given destination");
4602 } else { panic!(); }
4603
4604 let our_chans = [get_channel_details(Some(42), nodes[7].clone(),
4606 InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
4607 let route = get_route(&our_id, &route_params, &network_graph.read_only(),
4608 Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
4609 &Default::default(), &random_seed_bytes).unwrap();
4610 assert_eq!(route.paths[0].hops.len(), 2);
4611
4612 assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
4613 assert_eq!(route.paths[0].hops[0].short_channel_id, 42);
4614 assert_eq!(route.paths[0].hops[0].fee_msat, 200);
4615 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (13 << 4) | 1);
4616 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]);
4620 assert_eq!(route.paths[0].hops[1].short_channel_id, 13);
4621 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
4622 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
4623 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4624 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(13));
4625
4626 }
4630
4631 #[test]
4632 #[rustfmt::skip]
4633 fn our_chans_test() {
4634 let (secp_ctx, network_graph, _, _, logger) = build_graph();
4635 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
4636 let scorer = ln_test_utils::TestScorer::new();
4637 let random_seed_bytes = [42; 32];
4638
4639 let payment_params = PaymentParameters::from_node_id(nodes[0], 42);
4641 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4642 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4643 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4644 assert_eq!(route.paths[0].hops.len(), 3);
4645
4646 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
4647 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
4648 assert_eq!(route.paths[0].hops[0].fee_msat, 200);
4649 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
4650 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
4651 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
4652
4653 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
4654 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
4655 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
4656 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (3 << 4) | 2);
4657 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4658 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
4659
4660 assert_eq!(route.paths[0].hops[2].pubkey, nodes[0]);
4661 assert_eq!(route.paths[0].hops[2].short_channel_id, 3);
4662 assert_eq!(route.paths[0].hops[2].fee_msat, 100);
4663 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, 42);
4664 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(1));
4665 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(3));
4666
4667 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
4669 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4670 let our_chans = [get_channel_details(Some(42), nodes[7].clone(),
4671 InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
4672 let route = get_route(&our_id, &route_params, &network_graph.read_only(),
4673 Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
4674 &Default::default(), &random_seed_bytes).unwrap();
4675 assert_eq!(route.paths[0].hops.len(), 2);
4676
4677 assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
4678 assert_eq!(route.paths[0].hops[0].short_channel_id, 42);
4679 assert_eq!(route.paths[0].hops[0].fee_msat, 200);
4680 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (13 << 4) | 1);
4681 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &vec![0b11]);
4682 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &Vec::<u8>::new()); assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
4685 assert_eq!(route.paths[0].hops[1].short_channel_id, 13);
4686 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
4687 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
4688 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4689 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(13));
4690 }
4691
4692 #[rustfmt::skip]
4693 fn last_hops(nodes: &Vec<PublicKey>) -> Vec<RouteHint> {
4694 let zero_fees = RoutingFees {
4695 base_msat: 0,
4696 proportional_millionths: 0,
4697 };
4698 vec![RouteHint(vec![RouteHintHop {
4699 src_node_id: nodes[3],
4700 short_channel_id: 8,
4701 fees: zero_fees,
4702 cltv_expiry_delta: (8 << 4) | 1,
4703 htlc_minimum_msat: None,
4704 htlc_maximum_msat: None,
4705 }
4706 ]), RouteHint(vec![RouteHintHop {
4707 src_node_id: nodes[4],
4708 short_channel_id: 9,
4709 fees: RoutingFees {
4710 base_msat: 1001,
4711 proportional_millionths: 0,
4712 },
4713 cltv_expiry_delta: (9 << 4) | 1,
4714 htlc_minimum_msat: None,
4715 htlc_maximum_msat: None,
4716 }]), RouteHint(vec![RouteHintHop {
4717 src_node_id: nodes[5],
4718 short_channel_id: 10,
4719 fees: zero_fees,
4720 cltv_expiry_delta: (10 << 4) | 1,
4721 htlc_minimum_msat: None,
4722 htlc_maximum_msat: None,
4723 }])]
4724 }
4725
4726 #[rustfmt::skip]
4727 fn last_hops_multi_private_channels(nodes: &Vec<PublicKey>) -> Vec<RouteHint> {
4728 let zero_fees = RoutingFees {
4729 base_msat: 0,
4730 proportional_millionths: 0,
4731 };
4732 vec![RouteHint(vec![RouteHintHop {
4733 src_node_id: nodes[2],
4734 short_channel_id: 5,
4735 fees: RoutingFees {
4736 base_msat: 100,
4737 proportional_millionths: 0,
4738 },
4739 cltv_expiry_delta: (5 << 4) | 1,
4740 htlc_minimum_msat: None,
4741 htlc_maximum_msat: None,
4742 }, RouteHintHop {
4743 src_node_id: nodes[3],
4744 short_channel_id: 8,
4745 fees: zero_fees,
4746 cltv_expiry_delta: (8 << 4) | 1,
4747 htlc_minimum_msat: None,
4748 htlc_maximum_msat: None,
4749 }
4750 ]), RouteHint(vec![RouteHintHop {
4751 src_node_id: nodes[4],
4752 short_channel_id: 9,
4753 fees: RoutingFees {
4754 base_msat: 1001,
4755 proportional_millionths: 0,
4756 },
4757 cltv_expiry_delta: (9 << 4) | 1,
4758 htlc_minimum_msat: None,
4759 htlc_maximum_msat: None,
4760 }]), RouteHint(vec![RouteHintHop {
4761 src_node_id: nodes[5],
4762 short_channel_id: 10,
4763 fees: zero_fees,
4764 cltv_expiry_delta: (10 << 4) | 1,
4765 htlc_minimum_msat: None,
4766 htlc_maximum_msat: None,
4767 }])]
4768 }
4769
4770 #[test]
4771 #[rustfmt::skip]
4772 fn partial_route_hint_test() {
4773 let (secp_ctx, network_graph, _, _, logger) = build_graph();
4774 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
4775 let scorer = ln_test_utils::TestScorer::new();
4776 let random_seed_bytes = [42; 32];
4777
4778 let invalid_last_hop = RouteHint(vec![RouteHintHop {
4784 src_node_id: nodes[6],
4785 short_channel_id: 8,
4786 fees: RoutingFees {
4787 base_msat: 1000,
4788 proportional_millionths: 0,
4789 },
4790 cltv_expiry_delta: (8 << 4) | 1,
4791 htlc_minimum_msat: None,
4792 htlc_maximum_msat: None,
4793 }]);
4794
4795 let mut invalid_last_hops = last_hops_multi_private_channels(&nodes);
4796 invalid_last_hops.push(invalid_last_hop);
4797 {
4798 let payment_params = PaymentParameters::from_node_id(nodes[6], 42)
4799 .with_route_hints(invalid_last_hops).unwrap();
4800 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4801 if let Err(err) = get_route(&our_id,
4802 &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer,
4803 &Default::default(), &random_seed_bytes) {
4804 assert_eq!(err, "Route hint cannot have the payee as the source.");
4805 } else { panic!(); }
4806 }
4807
4808 let mut payment_params = PaymentParameters::from_node_id(nodes[6], 42)
4809 .with_route_hints(last_hops_multi_private_channels(&nodes)).unwrap();
4810 payment_params.max_path_length = 5;
4811 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4812 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4813 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4814 assert_eq!(route.paths[0].hops.len(), 5);
4815
4816 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
4817 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
4818 assert_eq!(route.paths[0].hops[0].fee_msat, 100);
4819 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
4820 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
4821 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
4822
4823 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
4824 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
4825 assert_eq!(route.paths[0].hops[1].fee_msat, 0);
4826 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (6 << 4) | 1);
4827 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4828 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
4829
4830 assert_eq!(route.paths[0].hops[2].pubkey, nodes[4]);
4831 assert_eq!(route.paths[0].hops[2].short_channel_id, 6);
4832 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
4833 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, (11 << 4) | 1);
4834 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(5));
4835 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(6));
4836
4837 assert_eq!(route.paths[0].hops[3].pubkey, nodes[3]);
4838 assert_eq!(route.paths[0].hops[3].short_channel_id, 11);
4839 assert_eq!(route.paths[0].hops[3].fee_msat, 0);
4840 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, (8 << 4) | 1);
4841 assert_eq!(route.paths[0].hops[3].node_features.le_flags(), &id_to_feature_flags(4));
4844 assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &id_to_feature_flags(11));
4845
4846 assert_eq!(route.paths[0].hops[4].pubkey, nodes[6]);
4847 assert_eq!(route.paths[0].hops[4].short_channel_id, 8);
4848 assert_eq!(route.paths[0].hops[4].fee_msat, 100);
4849 assert_eq!(route.paths[0].hops[4].cltv_expiry_delta, 42);
4850 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()); }
4853
4854 #[rustfmt::skip]
4855 fn empty_last_hop(nodes: &Vec<PublicKey>) -> Vec<RouteHint> {
4856 let zero_fees = RoutingFees {
4857 base_msat: 0,
4858 proportional_millionths: 0,
4859 };
4860 vec![RouteHint(vec![RouteHintHop {
4861 src_node_id: nodes[3],
4862 short_channel_id: 8,
4863 fees: zero_fees,
4864 cltv_expiry_delta: (8 << 4) | 1,
4865 htlc_minimum_msat: None,
4866 htlc_maximum_msat: None,
4867 }]), RouteHint(vec![
4868
4869 ]), RouteHint(vec![RouteHintHop {
4870 src_node_id: nodes[5],
4871 short_channel_id: 10,
4872 fees: zero_fees,
4873 cltv_expiry_delta: (10 << 4) | 1,
4874 htlc_minimum_msat: None,
4875 htlc_maximum_msat: None,
4876 }])]
4877 }
4878
4879 #[test]
4880 #[rustfmt::skip]
4881 fn ignores_empty_last_hops_test() {
4882 let (secp_ctx, network_graph, _, _, logger) = build_graph();
4883 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
4884 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(empty_last_hop(&nodes)).unwrap();
4885 let scorer = ln_test_utils::TestScorer::new();
4886 let random_seed_bytes = [42; 32];
4887
4888 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
4890 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
4891 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
4892 assert_eq!(route.paths[0].hops.len(), 5);
4893
4894 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
4895 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
4896 assert_eq!(route.paths[0].hops[0].fee_msat, 100);
4897 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
4898 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
4899 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
4900
4901 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
4902 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
4903 assert_eq!(route.paths[0].hops[1].fee_msat, 0);
4904 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (6 << 4) | 1);
4905 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
4906 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
4907
4908 assert_eq!(route.paths[0].hops[2].pubkey, nodes[4]);
4909 assert_eq!(route.paths[0].hops[2].short_channel_id, 6);
4910 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
4911 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, (11 << 4) | 1);
4912 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(5));
4913 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(6));
4914
4915 assert_eq!(route.paths[0].hops[3].pubkey, nodes[3]);
4916 assert_eq!(route.paths[0].hops[3].short_channel_id, 11);
4917 assert_eq!(route.paths[0].hops[3].fee_msat, 0);
4918 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, (8 << 4) | 1);
4919 assert_eq!(route.paths[0].hops[3].node_features.le_flags(), &id_to_feature_flags(4));
4922 assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &id_to_feature_flags(11));
4923
4924 assert_eq!(route.paths[0].hops[4].pubkey, nodes[6]);
4925 assert_eq!(route.paths[0].hops[4].short_channel_id, 8);
4926 assert_eq!(route.paths[0].hops[4].fee_msat, 100);
4927 assert_eq!(route.paths[0].hops[4].cltv_expiry_delta, 42);
4928 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()); }
4931
4932 #[rustfmt::skip]
4935 fn multi_hop_last_hops_hint(hint_hops: [PublicKey; 2]) -> Vec<RouteHint> {
4936 let zero_fees = RoutingFees {
4937 base_msat: 0,
4938 proportional_millionths: 0,
4939 };
4940 vec![RouteHint(vec![RouteHintHop {
4941 src_node_id: hint_hops[0],
4942 short_channel_id: 0xff00,
4943 fees: RoutingFees {
4944 base_msat: 100,
4945 proportional_millionths: 0,
4946 },
4947 cltv_expiry_delta: (5 << 4) | 1,
4948 htlc_minimum_msat: None,
4949 htlc_maximum_msat: None,
4950 }, RouteHintHop {
4951 src_node_id: hint_hops[1],
4952 short_channel_id: 0xff01,
4953 fees: zero_fees,
4954 cltv_expiry_delta: (8 << 4) | 1,
4955 htlc_minimum_msat: None,
4956 htlc_maximum_msat: None,
4957 }])]
4958 }
4959
4960 #[test]
4961 #[rustfmt::skip]
4962 fn multi_hint_last_hops_test() {
4963 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
4964 let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
4965 let last_hops = multi_hop_last_hops_hint([nodes[2], nodes[3]]);
4966 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops.clone()).unwrap();
4967 let scorer = ln_test_utils::TestScorer::new();
4968 let random_seed_bytes = [42; 32];
4969
4970 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
4976 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4977 short_channel_id: 6,
4978 timestamp: 2,
4979 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4982 htlc_minimum_msat: 0,
4983 htlc_maximum_msat: MAX_VALUE_MSAT,
4984 fee_base_msat: 0,
4985 fee_proportional_millionths: 0,
4986 excess_data: Vec::new()
4987 });
4988 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
4989 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
4990 short_channel_id: 7,
4991 timestamp: 2,
4992 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
4995 htlc_minimum_msat: 0,
4996 htlc_maximum_msat: MAX_VALUE_MSAT,
4997 fee_base_msat: 0,
4998 fee_proportional_millionths: 0,
4999 excess_data: Vec::new()
5000 });
5001
5002 let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
5003 route_params.payment_params.max_path_length = 4;
5004 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5005 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5006 assert_eq!(route.paths[0].hops.len(), 4);
5007
5008 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
5009 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
5010 assert_eq!(route.paths[0].hops[0].fee_msat, 200);
5011 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, 65);
5012 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
5013 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
5014
5015 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
5016 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
5017 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
5018 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 81);
5019 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
5020 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
5021
5022 assert_eq!(route.paths[0].hops[2].pubkey, nodes[3]);
5023 assert_eq!(route.paths[0].hops[2].short_channel_id, last_hops[0].0[0].short_channel_id);
5024 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
5025 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, 129);
5026 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(4));
5027 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &Vec::<u8>::new()); assert_eq!(route.paths[0].hops[3].pubkey, nodes[6]);
5030 assert_eq!(route.paths[0].hops[3].short_channel_id, last_hops[0].0[1].short_channel_id);
5031 assert_eq!(route.paths[0].hops[3].fee_msat, 100);
5032 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, 42);
5033 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;
5036 get_route(&our_id, &route_params, &network_graph.read_only(), None,
5037 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap_err();
5038 }
5039
5040 #[test]
5041 #[rustfmt::skip]
5042 fn private_multi_hint_last_hops_test() {
5043 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
5044 let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
5045
5046 let non_announced_privkey = SecretKey::from_slice(&<Vec<u8>>::from_hex(&format!("{:02x}", 0xf0).repeat(32)).unwrap()[..]).unwrap();
5047 let non_announced_pubkey = PublicKey::from_secret_key(&secp_ctx, &non_announced_privkey);
5048
5049 let last_hops = multi_hop_last_hops_hint([nodes[2], non_announced_pubkey]);
5050 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops.clone()).unwrap();
5051 let scorer = ln_test_utils::TestScorer::new();
5052 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
5057 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5058 short_channel_id: 6,
5059 timestamp: 2,
5060 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
5063 htlc_minimum_msat: 0,
5064 htlc_maximum_msat: MAX_VALUE_MSAT,
5065 fee_base_msat: 0,
5066 fee_proportional_millionths: 0,
5067 excess_data: Vec::new()
5068 });
5069 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
5070 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5071 short_channel_id: 7,
5072 timestamp: 2,
5073 message_flags: 1, channel_flags: 2, cltv_expiry_delta: 0,
5076 htlc_minimum_msat: 0,
5077 htlc_maximum_msat: MAX_VALUE_MSAT,
5078 fee_base_msat: 0,
5079 fee_proportional_millionths: 0,
5080 excess_data: Vec::new()
5081 });
5082
5083 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
5084 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5085 Arc::clone(&logger), &scorer, &Default::default(), &[42u8; 32]).unwrap();
5086 assert_eq!(route.paths[0].hops.len(), 4);
5087
5088 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
5089 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
5090 assert_eq!(route.paths[0].hops[0].fee_msat, 200);
5091 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, 65);
5092 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
5093 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
5094
5095 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
5096 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
5097 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
5098 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 81);
5099 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
5100 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
5101
5102 assert_eq!(route.paths[0].hops[2].pubkey, non_announced_pubkey);
5103 assert_eq!(route.paths[0].hops[2].short_channel_id, last_hops[0].0[0].short_channel_id);
5104 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
5105 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, 129);
5106 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]);
5110 assert_eq!(route.paths[0].hops[3].short_channel_id, last_hops[0].0[1].short_channel_id);
5111 assert_eq!(route.paths[0].hops[3].fee_msat, 100);
5112 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, 42);
5113 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()); }
5116
5117 #[rustfmt::skip]
5118 fn last_hops_with_public_channel(nodes: &Vec<PublicKey>) -> Vec<RouteHint> {
5119 let zero_fees = RoutingFees {
5120 base_msat: 0,
5121 proportional_millionths: 0,
5122 };
5123 vec![RouteHint(vec![RouteHintHop {
5124 src_node_id: nodes[4],
5125 short_channel_id: 11,
5126 fees: zero_fees,
5127 cltv_expiry_delta: (11 << 4) | 1,
5128 htlc_minimum_msat: None,
5129 htlc_maximum_msat: None,
5130 }, RouteHintHop {
5131 src_node_id: nodes[3],
5132 short_channel_id: 8,
5133 fees: zero_fees,
5134 cltv_expiry_delta: (8 << 4) | 1,
5135 htlc_minimum_msat: None,
5136 htlc_maximum_msat: None,
5137 }]), RouteHint(vec![RouteHintHop {
5138 src_node_id: nodes[4],
5139 short_channel_id: 9,
5140 fees: RoutingFees {
5141 base_msat: 1001,
5142 proportional_millionths: 0,
5143 },
5144 cltv_expiry_delta: (9 << 4) | 1,
5145 htlc_minimum_msat: None,
5146 htlc_maximum_msat: None,
5147 }]), RouteHint(vec![RouteHintHop {
5148 src_node_id: nodes[5],
5149 short_channel_id: 10,
5150 fees: zero_fees,
5151 cltv_expiry_delta: (10 << 4) | 1,
5152 htlc_minimum_msat: None,
5153 htlc_maximum_msat: None,
5154 }])]
5155 }
5156
5157 #[test]
5158 #[rustfmt::skip]
5159 fn last_hops_with_public_channel_test() {
5160 let (secp_ctx, network_graph, _, _, logger) = build_graph();
5161 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
5162 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops_with_public_channel(&nodes)).unwrap();
5163 let scorer = ln_test_utils::TestScorer::new();
5164 let random_seed_bytes = [42; 32];
5165
5166 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
5170 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5171 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5172 assert_eq!(route.paths[0].hops.len(), 5);
5173
5174 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
5175 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
5176 assert_eq!(route.paths[0].hops[0].fee_msat, 100);
5177 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
5178 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
5179 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
5180
5181 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
5182 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
5183 assert_eq!(route.paths[0].hops[1].fee_msat, 0);
5184 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (6 << 4) | 1);
5185 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
5186 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
5187
5188 assert_eq!(route.paths[0].hops[2].pubkey, nodes[4]);
5189 assert_eq!(route.paths[0].hops[2].short_channel_id, 6);
5190 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
5191 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, (11 << 4) | 1);
5192 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(5));
5193 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(6));
5194
5195 assert_eq!(route.paths[0].hops[3].pubkey, nodes[3]);
5196 assert_eq!(route.paths[0].hops[3].short_channel_id, 11);
5197 assert_eq!(route.paths[0].hops[3].fee_msat, 0);
5198 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, (8 << 4) | 1);
5199 assert_eq!(route.paths[0].hops[3].node_features.le_flags(), &id_to_feature_flags(4));
5202 assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &id_to_feature_flags(11));
5203
5204 assert_eq!(route.paths[0].hops[4].pubkey, nodes[6]);
5205 assert_eq!(route.paths[0].hops[4].short_channel_id, 8);
5206 assert_eq!(route.paths[0].hops[4].fee_msat, 100);
5207 assert_eq!(route.paths[0].hops[4].cltv_expiry_delta, 42);
5208 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()); }
5211
5212 #[test]
5213 #[rustfmt::skip]
5214 fn our_chans_last_hop_connect_test() {
5215 let (secp_ctx, network_graph, _, _, logger) = build_graph();
5216 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
5217 let scorer = ln_test_utils::TestScorer::new();
5218 let random_seed_bytes = [42; 32];
5219
5220 let our_chans = [get_channel_details(Some(42), nodes[3].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
5222 let mut last_hops = last_hops(&nodes);
5223 let payment_params = PaymentParameters::from_node_id(nodes[6], 42)
5224 .with_route_hints(last_hops.clone()).unwrap();
5225 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
5226 let route = get_route(&our_id, &route_params, &network_graph.read_only(),
5227 Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
5228 &Default::default(), &random_seed_bytes).unwrap();
5229 assert_eq!(route.paths[0].hops.len(), 2);
5230
5231 assert_eq!(route.paths[0].hops[0].pubkey, nodes[3]);
5232 assert_eq!(route.paths[0].hops[0].short_channel_id, 42);
5233 assert_eq!(route.paths[0].hops[0].fee_msat, 0);
5234 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (8 << 4) | 1);
5235 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &vec![0b11]);
5236 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &Vec::<u8>::new()); assert_eq!(route.paths[0].hops[1].pubkey, nodes[6]);
5239 assert_eq!(route.paths[0].hops[1].short_channel_id, 8);
5240 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
5241 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
5242 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;
5246
5247 let payment_params = PaymentParameters::from_node_id(nodes[6], 42)
5249 .with_route_hints(last_hops).unwrap();
5250 let route_params = RouteParameters::from_payment_params_and_value(
5251 payment_params.clone(), 100);
5252 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5253 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5254 assert_eq!(route.paths[0].hops.len(), 4);
5255
5256 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
5257 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
5258 assert_eq!(route.paths[0].hops[0].fee_msat, 200); assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
5260 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
5261 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
5262
5263 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
5264 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
5265 assert_eq!(route.paths[0].hops[1].fee_msat, 100);
5266 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (7 << 4) | 1);
5267 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
5268 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
5269
5270 assert_eq!(route.paths[0].hops[2].pubkey, nodes[5]);
5271 assert_eq!(route.paths[0].hops[2].short_channel_id, 7);
5272 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
5273 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, (10 << 4) | 1);
5274 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(6));
5277 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(7));
5278
5279 assert_eq!(route.paths[0].hops[3].pubkey, nodes[6]);
5280 assert_eq!(route.paths[0].hops[3].short_channel_id, 10);
5281 assert_eq!(route.paths[0].hops[3].fee_msat, 100);
5282 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, 42);
5283 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);
5288 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5289 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5290 assert_eq!(route.paths[0].hops.len(), 5);
5291
5292 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
5293 assert_eq!(route.paths[0].hops[0].short_channel_id, 2);
5294 assert_eq!(route.paths[0].hops[0].fee_msat, 3000);
5295 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (4 << 4) | 1);
5296 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(2));
5297 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(2));
5298
5299 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
5300 assert_eq!(route.paths[0].hops[1].short_channel_id, 4);
5301 assert_eq!(route.paths[0].hops[1].fee_msat, 0);
5302 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (6 << 4) | 1);
5303 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
5304 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(4));
5305
5306 assert_eq!(route.paths[0].hops[2].pubkey, nodes[4]);
5307 assert_eq!(route.paths[0].hops[2].short_channel_id, 6);
5308 assert_eq!(route.paths[0].hops[2].fee_msat, 0);
5309 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, (11 << 4) | 1);
5310 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(5));
5311 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(6));
5312
5313 assert_eq!(route.paths[0].hops[3].pubkey, nodes[3]);
5314 assert_eq!(route.paths[0].hops[3].short_channel_id, 11);
5315 assert_eq!(route.paths[0].hops[3].fee_msat, 1000);
5316 assert_eq!(route.paths[0].hops[3].cltv_expiry_delta, (8 << 4) | 1);
5317 assert_eq!(route.paths[0].hops[3].node_features.le_flags(), &id_to_feature_flags(4));
5320 assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &id_to_feature_flags(11));
5321
5322 assert_eq!(route.paths[0].hops[4].pubkey, nodes[6]);
5323 assert_eq!(route.paths[0].hops[4].short_channel_id, 8);
5324 assert_eq!(route.paths[0].hops[4].fee_msat, 2000);
5325 assert_eq!(route.paths[0].hops[4].cltv_expiry_delta, 42);
5326 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()); }
5329
5330 #[rustfmt::skip]
5331 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> {
5332 let source_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&<Vec<u8>>::from_hex(&format!("{:02}", 41).repeat(32)).unwrap()[..]).unwrap());
5333 let middle_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&<Vec<u8>>::from_hex(&format!("{:02}", 42).repeat(32)).unwrap()[..]).unwrap());
5334 let target_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&<Vec<u8>>::from_hex(&format!("{:02}", 43).repeat(32)).unwrap()[..]).unwrap());
5335
5336 let last_hops = RouteHint(vec![RouteHintHop {
5338 src_node_id: middle_node_id,
5339 short_channel_id: 8,
5340 fees: RoutingFees {
5341 base_msat: 1000,
5342 proportional_millionths: last_hop_fee_prop,
5343 },
5344 cltv_expiry_delta: (8 << 4) | 1,
5345 htlc_minimum_msat: None,
5346 htlc_maximum_msat: last_hop_htlc_max,
5347 }]);
5348 let payment_params = PaymentParameters::from_node_id(target_node_id, 42).with_route_hints(vec![last_hops]).unwrap();
5349 let our_chans = [get_channel_details(Some(42), middle_node_id, InitFeatures::from_le_bytes(vec![0b11]), outbound_capacity_msat)];
5350 let scorer = ln_test_utils::TestScorer::new();
5351 let random_seed_bytes = [42; 32];
5352 let logger = ln_test_utils::TestLogger::new();
5353 let network_graph = NetworkGraph::new(Network::Testnet, &logger);
5354 let route_params = RouteParameters::from_payment_params_and_value(payment_params, route_val);
5355 let route = get_route(&source_node_id, &route_params, &network_graph.read_only(),
5356 Some(&our_chans.iter().collect::<Vec<_>>()), &logger, &scorer, &Default::default(),
5357 &random_seed_bytes);
5358 route
5359 }
5360
5361 #[test]
5362 #[rustfmt::skip]
5363 fn unannounced_path_test() {
5364 let route = do_unannounced_path_test(None, 1, 2000000, 1000000).unwrap();
5368
5369 let middle_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&<Vec<u8>>::from_hex(&format!("{:02}", 42).repeat(32)).unwrap()[..]).unwrap());
5370 let target_node_id = PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&<Vec<u8>>::from_hex(&format!("{:02}", 43).repeat(32)).unwrap()[..]).unwrap());
5371 assert_eq!(route.paths[0].hops.len(), 2);
5372
5373 assert_eq!(route.paths[0].hops[0].pubkey, middle_node_id);
5374 assert_eq!(route.paths[0].hops[0].short_channel_id, 42);
5375 assert_eq!(route.paths[0].hops[0].fee_msat, 1001);
5376 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (8 << 4) | 1);
5377 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &[0b11]);
5378 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &[0; 0]); assert_eq!(route.paths[0].hops[1].pubkey, target_node_id);
5381 assert_eq!(route.paths[0].hops[1].short_channel_id, 8);
5382 assert_eq!(route.paths[0].hops[1].fee_msat, 1000000);
5383 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
5384 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]); }
5387
5388 #[test]
5389 #[rustfmt::skip]
5390 fn overflow_unannounced_path_test_liquidity_underflow() {
5391 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());
5398 }
5399
5400 #[test]
5401 #[rustfmt::skip]
5402 fn overflow_unannounced_path_test_feerate_overflow() {
5403 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());
5406 }
5407
5408 #[test]
5409 #[rustfmt::skip]
5410 fn available_amount_while_routing_test() {
5411 let (secp_ctx, network_graph, gossip_sync, chain_monitor, logger) = build_graph();
5414 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
5415 let scorer = ln_test_utils::TestScorer::new();
5416 let random_seed_bytes = [42; 32];
5417 let config = UserConfig::default();
5418 let payment_params = PaymentParameters::from_node_id(nodes[2], 42)
5419 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
5420 .unwrap();
5421
5422 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5427 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5428 short_channel_id: 2,
5429 timestamp: 2,
5430 message_flags: 1, channel_flags: 2,
5432 cltv_expiry_delta: 0,
5433 htlc_minimum_msat: 0,
5434 htlc_maximum_msat: 100_000,
5435 fee_base_msat: 0,
5436 fee_proportional_millionths: 0,
5437 excess_data: Vec::new()
5438 });
5439 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5440 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5441 short_channel_id: 12,
5442 timestamp: 2,
5443 message_flags: 1, channel_flags: 2,
5445 cltv_expiry_delta: 0,
5446 htlc_minimum_msat: 0,
5447 htlc_maximum_msat: 100_000,
5448 fee_base_msat: 0,
5449 fee_proportional_millionths: 0,
5450 excess_data: Vec::new()
5451 });
5452
5453 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5456 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5457 short_channel_id: 1,
5458 timestamp: 2,
5459 message_flags: 1, channel_flags: 0,
5461 cltv_expiry_delta: 0,
5462 htlc_minimum_msat: 0,
5463 htlc_maximum_msat: 1_000_000_000,
5464 fee_base_msat: 0,
5465 fee_proportional_millionths: 0,
5466 excess_data: Vec::new()
5467 });
5468
5469 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5472 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5473 short_channel_id: 3,
5474 timestamp: 2,
5475 message_flags: 1, channel_flags: 0,
5477 cltv_expiry_delta: 0,
5478 htlc_minimum_msat: 0,
5479 htlc_maximum_msat: 250_000_000,
5480 fee_base_msat: 0,
5481 fee_proportional_millionths: 0,
5482 excess_data: Vec::new()
5483 });
5484
5485 {
5486 let route_params = RouteParameters::from_payment_params_and_value(
5488 payment_params.clone(), 250_000_001);
5489 if let Err(err) = get_route(
5490 &our_id, &route_params, &network_graph.read_only(), None,
5491 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) {
5492 assert_eq!(err, "Failed to find a sufficient route to the given destination");
5493 } else { panic!(); }
5494 }
5495
5496 {
5497 let route_params = RouteParameters::from_payment_params_and_value(
5499 payment_params.clone(), 250_000_000);
5500 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5501 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5502 assert_eq!(route.paths.len(), 1);
5503 let path = route.paths.last().unwrap();
5504 assert_eq!(path.hops.len(), 2);
5505 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
5506 assert_eq!(path.final_value_msat(), 250_000_000);
5507 }
5508
5509 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5512 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5513 short_channel_id: 1,
5514 timestamp: 3,
5515 message_flags: 1, channel_flags: 2,
5517 cltv_expiry_delta: 0,
5518 htlc_minimum_msat: 0,
5519 htlc_maximum_msat: 1_000_000_000,
5520 fee_base_msat: 0,
5521 fee_proportional_millionths: 0,
5522 excess_data: Vec::new()
5523 });
5524
5525 let our_chans = [get_channel_details(Some(42), nodes[0].clone(), InitFeatures::from_le_bytes(vec![0b11]), 200_000_000)];
5527
5528 {
5529 let route_params = RouteParameters::from_payment_params_and_value(
5531 payment_params.clone(), 200_000_001);
5532 if let Err(err) = get_route(
5533 &our_id, &route_params, &network_graph.read_only(),
5534 Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
5535 &Default::default(), &random_seed_bytes) {
5536 assert_eq!(err, "Failed to find a sufficient route to the given destination");
5537 } else { panic!(); }
5538 }
5539
5540 {
5541 let route_params = RouteParameters::from_payment_params_and_value(
5543 payment_params.clone(), 200_000_000);
5544 let route = get_route(&our_id, &route_params, &network_graph.read_only(),
5545 Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
5546 &Default::default(), &random_seed_bytes).unwrap();
5547 assert_eq!(route.paths.len(), 1);
5548 let path = route.paths.last().unwrap();
5549 assert_eq!(path.hops.len(), 2);
5550 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
5551 assert_eq!(path.final_value_msat(), 200_000_000);
5552 }
5553
5554 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5556 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5557 short_channel_id: 1,
5558 timestamp: 4,
5559 message_flags: 1, channel_flags: 0,
5561 cltv_expiry_delta: 0,
5562 htlc_minimum_msat: 0,
5563 htlc_maximum_msat: 1_000_000_000,
5564 fee_base_msat: 0,
5565 fee_proportional_millionths: 0,
5566 excess_data: Vec::new()
5567 });
5568
5569
5570 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5572 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5573 short_channel_id: 3,
5574 timestamp: 3,
5575 message_flags: 1, channel_flags: 0,
5577 cltv_expiry_delta: 0,
5578 htlc_minimum_msat: 0,
5579 htlc_maximum_msat: 15_000,
5580 fee_base_msat: 0,
5581 fee_proportional_millionths: 0,
5582 excess_data: Vec::new()
5583 });
5584
5585 {
5586 let route_params = RouteParameters::from_payment_params_and_value(
5588 payment_params.clone(), 15_001);
5589 if let Err(err) = get_route(
5590 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
5591 &scorer, &Default::default(), &random_seed_bytes) {
5592 assert_eq!(err, "Failed to find a sufficient route to the given destination");
5593 } else { panic!(); }
5594 }
5595
5596 {
5597 let route_params = RouteParameters::from_payment_params_and_value(
5599 payment_params.clone(), 15_000);
5600 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5601 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5602 assert_eq!(route.paths.len(), 1);
5603 let path = route.paths.last().unwrap();
5604 assert_eq!(path.hops.len(), 2);
5605 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
5606 assert_eq!(path.final_value_msat(), 15_000);
5607 }
5608
5609 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5614 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5615 short_channel_id: 3,
5616 timestamp: 4,
5617 message_flags: 1, channel_flags: 2,
5619 cltv_expiry_delta: 0,
5620 htlc_minimum_msat: 0,
5621 htlc_maximum_msat: MAX_VALUE_MSAT,
5622 fee_base_msat: 0,
5623 fee_proportional_millionths: 0,
5624 excess_data: Vec::new()
5625 });
5626
5627 let good_script = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2)
5628 .push_slice(&PublicKey::from_secret_key(&secp_ctx, &privkeys[0]).serialize())
5629 .push_slice(&PublicKey::from_secret_key(&secp_ctx, &privkeys[2]).serialize())
5630 .push_opcode(opcodes::all::OP_PUSHNUM_2)
5631 .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_p2wsh();
5632
5633 *chain_monitor.utxo_ret.lock().unwrap() =
5634 UtxoResult::Sync(Ok(TxOut { value: Amount::from_sat(15), script_pubkey: good_script.clone() }));
5635 gossip_sync.add_utxo_lookup(Some(chain_monitor));
5636
5637 add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 333);
5638 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5639 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5640 short_channel_id: 333,
5641 timestamp: 1,
5642 message_flags: 1, channel_flags: 0,
5644 cltv_expiry_delta: (3 << 4) | 1,
5645 htlc_minimum_msat: 0,
5646 htlc_maximum_msat: 15_000,
5647 fee_base_msat: 0,
5648 fee_proportional_millionths: 0,
5649 excess_data: Vec::new()
5650 });
5651 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
5652 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5653 short_channel_id: 333,
5654 timestamp: 1,
5655 message_flags: 1, channel_flags: 1,
5657 cltv_expiry_delta: (3 << 4) | 2,
5658 htlc_minimum_msat: 0,
5659 htlc_maximum_msat: 15_000,
5660 fee_base_msat: 100,
5661 fee_proportional_millionths: 0,
5662 excess_data: Vec::new()
5663 });
5664
5665 {
5666 let route_params = RouteParameters::from_payment_params_and_value(
5668 payment_params.clone(), 15_001);
5669 if let Err(err) = get_route(
5670 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
5671 &scorer, &Default::default(), &random_seed_bytes) {
5672 assert_eq!(err, "Failed to find a sufficient route to the given destination");
5673 } else { panic!(); }
5674 }
5675
5676 {
5677 let route_params = RouteParameters::from_payment_params_and_value(
5679 payment_params.clone(), 15_000);
5680 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5681 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5682 assert_eq!(route.paths.len(), 1);
5683 let path = route.paths.last().unwrap();
5684 assert_eq!(path.hops.len(), 2);
5685 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
5686 assert_eq!(path.final_value_msat(), 15_000);
5687 }
5688
5689 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5691 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5692 short_channel_id: 333,
5693 timestamp: 6,
5694 message_flags: 1, channel_flags: 0,
5696 cltv_expiry_delta: 0,
5697 htlc_minimum_msat: 0,
5698 htlc_maximum_msat: 10_000,
5699 fee_base_msat: 0,
5700 fee_proportional_millionths: 0,
5701 excess_data: Vec::new()
5702 });
5703
5704 {
5705 let route_params = RouteParameters::from_payment_params_and_value(
5707 payment_params.clone(), 10_001);
5708 if let Err(err) = get_route(
5709 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
5710 &scorer, &Default::default(), &random_seed_bytes) {
5711 assert_eq!(err, "Failed to find a sufficient route to the given destination");
5712 } else { panic!(); }
5713 }
5714
5715 {
5716 let route_params = RouteParameters::from_payment_params_and_value(
5718 payment_params.clone(), 10_000);
5719 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5720 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5721 assert_eq!(route.paths.len(), 1);
5722 let path = route.paths.last().unwrap();
5723 assert_eq!(path.hops.len(), 2);
5724 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
5725 assert_eq!(path.final_value_msat(), 10_000);
5726 }
5727 }
5728
5729 #[test]
5730 #[rustfmt::skip]
5731 fn available_liquidity_last_hop_test() {
5732 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
5735 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
5736 let scorer = ln_test_utils::TestScorer::new();
5737 let random_seed_bytes = [42; 32];
5738 let config = UserConfig::default();
5739 let payment_params = PaymentParameters::from_node_id(nodes[3], 42)
5740 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
5741 .unwrap();
5742
5743 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5749 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5750 short_channel_id: 2,
5751 timestamp: 2,
5752 message_flags: 1, channel_flags: 2,
5754 cltv_expiry_delta: 0,
5755 htlc_minimum_msat: 0,
5756 htlc_maximum_msat: 100_000,
5757 fee_base_msat: 0,
5758 fee_proportional_millionths: 0,
5759 excess_data: Vec::new()
5760 });
5761 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
5762 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5763 short_channel_id: 7,
5764 timestamp: 2,
5765 message_flags: 1, channel_flags: 2,
5767 cltv_expiry_delta: 0,
5768 htlc_minimum_msat: 0,
5769 htlc_maximum_msat: 100_000,
5770 fee_base_msat: 0,
5771 fee_proportional_millionths: 0,
5772 excess_data: Vec::new()
5773 });
5774
5775 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5778 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5779 short_channel_id: 12,
5780 timestamp: 2,
5781 message_flags: 1, channel_flags: 0,
5783 cltv_expiry_delta: 0,
5784 htlc_minimum_msat: 0,
5785 htlc_maximum_msat: 100_000,
5786 fee_base_msat: 0,
5787 fee_proportional_millionths: 0,
5788 excess_data: Vec::new()
5789 });
5790 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
5791 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5792 short_channel_id: 13,
5793 timestamp: 2,
5794 message_flags: 1, channel_flags: 0,
5796 cltv_expiry_delta: 0,
5797 htlc_minimum_msat: 0,
5798 htlc_maximum_msat: 100_000,
5799 fee_base_msat: 0,
5800 fee_proportional_millionths: 0,
5801 excess_data: Vec::new()
5802 });
5803
5804 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
5805 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5806 short_channel_id: 6,
5807 timestamp: 2,
5808 message_flags: 1, channel_flags: 0,
5810 cltv_expiry_delta: 0,
5811 htlc_minimum_msat: 0,
5812 htlc_maximum_msat: 50_000,
5813 fee_base_msat: 0,
5814 fee_proportional_millionths: 0,
5815 excess_data: Vec::new()
5816 });
5817 update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
5818 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5819 short_channel_id: 11,
5820 timestamp: 2,
5821 message_flags: 1, channel_flags: 0,
5823 cltv_expiry_delta: 0,
5824 htlc_minimum_msat: 0,
5825 htlc_maximum_msat: 100_000,
5826 fee_base_msat: 0,
5827 fee_proportional_millionths: 0,
5828 excess_data: Vec::new()
5829 });
5830 {
5831 let route_params = RouteParameters::from_payment_params_and_value(
5833 payment_params.clone(), 60_000);
5834 if let Err(err) = get_route(
5835 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
5836 &scorer, &Default::default(), &random_seed_bytes) {
5837 assert_eq!(err, "Failed to find a sufficient route to the given destination");
5838 } else { panic!(); }
5839 }
5840
5841 {
5842 let route_params = RouteParameters::from_payment_params_and_value(
5844 payment_params.clone(), 49_000);
5845 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5846 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5847 assert_eq!(route.paths.len(), 1);
5848 let mut total_amount_paid_msat = 0;
5849 for path in &route.paths {
5850 assert_eq!(path.hops.len(), 4);
5851 assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]);
5852 total_amount_paid_msat += path.final_value_msat();
5853 }
5854 assert_eq!(total_amount_paid_msat, 49_000);
5855 }
5856
5857 {
5858 let route_params = RouteParameters::from_payment_params_and_value(
5860 payment_params, 50_000);
5861 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5862 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5863 assert_eq!(route.paths.len(), 1);
5864 let mut total_amount_paid_msat = 0;
5865 for path in &route.paths {
5866 assert_eq!(path.hops.len(), 4);
5867 assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]);
5868 total_amount_paid_msat += path.final_value_msat();
5869 }
5870 assert_eq!(total_amount_paid_msat, 50_000);
5871 }
5872 }
5873
5874 #[test]
5875 #[rustfmt::skip]
5876 fn ignore_fee_first_hop_test() {
5877 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
5878 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
5879 let scorer = ln_test_utils::TestScorer::new();
5880 let random_seed_bytes = [42; 32];
5881 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
5882
5883 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5885 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5886 short_channel_id: 1,
5887 timestamp: 2,
5888 message_flags: 1, channel_flags: 0,
5890 cltv_expiry_delta: 0,
5891 htlc_minimum_msat: 0,
5892 htlc_maximum_msat: 100_000,
5893 fee_base_msat: 1_000_000,
5894 fee_proportional_millionths: 0,
5895 excess_data: Vec::new()
5896 });
5897 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
5898 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5899 short_channel_id: 3,
5900 timestamp: 2,
5901 message_flags: 1, channel_flags: 0,
5903 cltv_expiry_delta: 0,
5904 htlc_minimum_msat: 0,
5905 htlc_maximum_msat: 50_000,
5906 fee_base_msat: 0,
5907 fee_proportional_millionths: 0,
5908 excess_data: Vec::new()
5909 });
5910
5911 {
5912 let route_params = RouteParameters::from_payment_params_and_value(
5913 payment_params, 50_000);
5914 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
5915 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
5916 assert_eq!(route.paths.len(), 1);
5917 let mut total_amount_paid_msat = 0;
5918 for path in &route.paths {
5919 assert_eq!(path.hops.len(), 2);
5920 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
5921 total_amount_paid_msat += path.final_value_msat();
5922 }
5923 assert_eq!(total_amount_paid_msat, 50_000);
5924 }
5925 }
5926
5927 #[test]
5928 #[rustfmt::skip]
5929 fn simple_mpp_route_test() {
5930 let (secp_ctx, _, _, _, _) = build_graph();
5931 let (_, _, _, nodes) = get_nodes(&secp_ctx);
5932 let config = UserConfig::default();
5933 let clear_payment_params = PaymentParameters::from_node_id(nodes[2], 42)
5934 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
5935 .unwrap();
5936 do_simple_mpp_route_test(clear_payment_params);
5937
5938 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
5940 let blinded_payinfo = BlindedPayInfo { fee_base_msat: 0,
5942 fee_proportional_millionths: 0,
5943 htlc_minimum_msat: 0,
5944 htlc_maximum_msat: 0,
5945 cltv_expiry_delta: 0,
5946 features: BlindedHopFeatures::empty(),
5947 };
5948 let blinded_path = dummy_one_hop_blinded_path(nodes[2], blinded_payinfo.clone());
5949 let one_hop_blinded_payment_params = PaymentParameters::blinded(vec![blinded_path.clone()])
5950 .with_bolt12_features(bolt12_features.clone()).unwrap();
5951 do_simple_mpp_route_test(one_hop_blinded_payment_params.clone());
5952
5953 let mut node_0_payinfo = blinded_payinfo.clone();
5955 node_0_payinfo.htlc_maximum_msat = 50_000;
5956 let blinded_path_node_0 = dummy_blinded_path(nodes[0], node_0_payinfo);
5957
5958 let mut node_7_payinfo = blinded_payinfo.clone();
5959 node_7_payinfo.htlc_maximum_msat = 60_000;
5960 let blinded_path_node_7 = dummy_blinded_path(nodes[7], node_7_payinfo);
5961
5962 let mut node_1_payinfo = blinded_payinfo;
5963 node_1_payinfo.htlc_maximum_msat = 180_000;
5964 let blinded_path_node_1 = dummy_blinded_path(nodes[1], node_1_payinfo);
5965
5966 let two_hop_blinded_payment_params = PaymentParameters::blinded(
5967 vec![blinded_path_node_0, blinded_path_node_7, blinded_path_node_1])
5968 .with_bolt12_features(bolt12_features).unwrap();
5969 do_simple_mpp_route_test(two_hop_blinded_payment_params);
5970 }
5971
5972 #[rustfmt::skip]
5973 fn do_simple_mpp_route_test(payment_params: PaymentParameters) {
5974 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
5975 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
5976 let scorer = ln_test_utils::TestScorer::new();
5977 let random_seed_bytes = [42; 32];
5978
5979 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
5989 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
5990 short_channel_id: 1,
5991 timestamp: 2,
5992 message_flags: 1, channel_flags: 0,
5994 cltv_expiry_delta: 0,
5995 htlc_minimum_msat: 0,
5996 htlc_maximum_msat: 100_000,
5997 fee_base_msat: 0,
5998 fee_proportional_millionths: 0,
5999 excess_data: Vec::new()
6000 });
6001 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
6002 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6003 short_channel_id: 3,
6004 timestamp: 2,
6005 message_flags: 1, channel_flags: 0,
6007 cltv_expiry_delta: 0,
6008 htlc_minimum_msat: 0,
6009 htlc_maximum_msat: 50_000,
6010 fee_base_msat: 0,
6011 fee_proportional_millionths: 0,
6012 excess_data: Vec::new()
6013 });
6014
6015 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6018 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6019 short_channel_id: 12,
6020 timestamp: 2,
6021 message_flags: 1, channel_flags: 0,
6023 cltv_expiry_delta: 0,
6024 htlc_minimum_msat: 0,
6025 htlc_maximum_msat: 60_000,
6026 fee_base_msat: 0,
6027 fee_proportional_millionths: 0,
6028 excess_data: Vec::new()
6029 });
6030 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
6031 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6032 short_channel_id: 13,
6033 timestamp: 2,
6034 message_flags: 1, channel_flags: 0,
6036 cltv_expiry_delta: 0,
6037 htlc_minimum_msat: 0,
6038 htlc_maximum_msat: 60_000,
6039 fee_base_msat: 0,
6040 fee_proportional_millionths: 0,
6041 excess_data: Vec::new()
6042 });
6043
6044 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6047 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6048 short_channel_id: 2,
6049 timestamp: 2,
6050 message_flags: 1, channel_flags: 0,
6052 cltv_expiry_delta: 0,
6053 htlc_minimum_msat: 0,
6054 htlc_maximum_msat: 200_000,
6055 fee_base_msat: 0,
6056 fee_proportional_millionths: 0,
6057 excess_data: Vec::new()
6058 });
6059 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
6060 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6061 short_channel_id: 4,
6062 timestamp: 2,
6063 message_flags: 1, channel_flags: 0,
6065 cltv_expiry_delta: 0,
6066 htlc_minimum_msat: 0,
6067 htlc_maximum_msat: 180_000,
6068 fee_base_msat: 0,
6069 fee_proportional_millionths: 0,
6070 excess_data: Vec::new()
6071 });
6072
6073 {
6074 let route_params = RouteParameters::from_payment_params_and_value(
6076 payment_params.clone(), 300_000);
6077 if let Err(err) = get_route(
6078 &our_id, &route_params, &network_graph.read_only(), None,
6079 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) {
6080 assert_eq!(err, "Failed to find a sufficient route to the given destination");
6081 } else { panic!(); }
6082 }
6083
6084 {
6085 let zero_payment_params = payment_params.clone().with_max_path_count(0);
6087 let route_params = RouteParameters::from_payment_params_and_value(
6088 zero_payment_params, 100);
6089 if let Err(err) = get_route(
6090 &our_id, &route_params, &network_graph.read_only(), None,
6091 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) {
6092 assert_eq!(err, "Can't find a route with no paths allowed.");
6093 } else { panic!(); }
6094 }
6095
6096 {
6097 let fail_payment_params = payment_params.clone().with_max_path_count(3);
6101 let route_params = RouteParameters::from_payment_params_and_value(
6102 fail_payment_params, 250_000);
6103 if let Err(err) = get_route(
6104 &our_id, &route_params, &network_graph.read_only(), None,
6105 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes) {
6106 assert_eq!(err, "Failed to find a sufficient route to the given destination");
6107 } else { panic!(); }
6108 }
6109
6110 {
6111 let route_params = RouteParameters::from_payment_params_and_value(
6114 payment_params.clone(), 250_000);
6115 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6116 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6117 assert_eq!(route.paths.len(), 3);
6118 let mut total_amount_paid_msat = 0;
6119 for path in &route.paths {
6120 if let Some(bt) = &path.blinded_tail {
6121 assert_eq!(path.hops.len() + if bt.hops.len() == 1 { 0 } else { 1 }, 2);
6122 } else {
6123 assert_eq!(path.hops.len(), 2);
6124 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
6125 }
6126 total_amount_paid_msat += path.final_value_msat();
6127 }
6128 assert_eq!(total_amount_paid_msat, 250_000);
6129 }
6130
6131 {
6132 let route_params = RouteParameters::from_payment_params_and_value(
6134 payment_params.clone(), 290_000);
6135 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6136 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6137 assert_eq!(route.paths.len(), 3);
6138 let mut total_amount_paid_msat = 0;
6139 for path in &route.paths {
6140 if payment_params.payee.blinded_route_hints().len() != 0 {
6141 assert!(path.blinded_tail.is_some()) } else { assert!(path.blinded_tail.is_none()) }
6142 if let Some(bt) = &path.blinded_tail {
6143 assert_eq!(path.hops.len() + if bt.hops.len() == 1 { 0 } else { 1 }, 2);
6144 if bt.hops.len() > 1 {
6145 let network_graph = network_graph.read_only();
6146 assert_eq!(
6147 NodeId::from_pubkey(&path.hops.last().unwrap().pubkey),
6148 payment_params.payee.blinded_route_hints().iter()
6149 .find(|p| p.payinfo.htlc_maximum_msat == path.final_value_msat())
6150 .and_then(|p| p.public_introduction_node_id(&network_graph))
6151 .copied()
6152 .unwrap()
6153 );
6154 } else {
6155 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
6156 }
6157 } else {
6158 assert_eq!(path.hops.len(), 2);
6159 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
6160 }
6161 total_amount_paid_msat += path.final_value_msat();
6162 }
6163 assert_eq!(total_amount_paid_msat, 290_000);
6164 }
6165 }
6166
6167 #[test]
6168 fn mpp_tests() {
6169 let secp_ctx = Secp256k1::new();
6170 let (_, _, _, nodes) = get_nodes(&secp_ctx);
6171 {
6172 let route = do_mpp_route_tests(180_000).unwrap();
6175 assert_eq!(route.paths.len(), 2);
6176
6177 let mut total_value_transferred_msat = 0;
6178 let mut total_paid_msat = 0;
6179 for path in &route.paths {
6180 assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]);
6181 total_value_transferred_msat += path.final_value_msat();
6182 for hop in &path.hops {
6183 total_paid_msat += hop.fee_msat;
6184 }
6185 }
6186 assert_eq!(total_value_transferred_msat, 180_000);
6188 let total_fees_paid = total_paid_msat - total_value_transferred_msat;
6189 assert_eq!(total_fees_paid, 0);
6190 }
6191 {
6192 let route = do_mpp_route_tests(300_000).unwrap();
6195 assert_eq!(route.paths.len(), 3);
6196
6197 let mut total_amount_paid_msat = 0;
6198 for path in &route.paths {
6199 assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]);
6200 total_amount_paid_msat += path.final_value_msat();
6201 }
6202 assert_eq!(total_amount_paid_msat, 300_000);
6203 }
6204 assert!(do_mpp_route_tests(300_001).is_err());
6206 }
6207
6208 #[rustfmt::skip]
6209 fn do_mpp_route_tests(amt: u64) -> Result<Route, &'static str> {
6210 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
6211 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
6212 let scorer = ln_test_utils::TestScorer::new();
6213 let random_seed_bytes = [42; 32];
6214 let config = UserConfig::default();
6215 let payment_params = PaymentParameters::from_node_id(nodes[3], 42)
6216 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
6217 .unwrap();
6218
6219 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
6228 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6229 short_channel_id: 7,
6230 timestamp: 2,
6231 message_flags: 1, channel_flags: 2,
6233 cltv_expiry_delta: 0,
6234 htlc_minimum_msat: 0,
6235 htlc_maximum_msat: 100_000,
6236 fee_base_msat: 0,
6237 fee_proportional_millionths: 0,
6238 excess_data: Vec::new()
6239 });
6240 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
6241 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6242 short_channel_id: 4,
6243 timestamp: 2,
6244 message_flags: 1, channel_flags: 2,
6246 cltv_expiry_delta: 0,
6247 htlc_minimum_msat: 0,
6248 htlc_maximum_msat: 100_000,
6249 fee_base_msat: 0,
6250 fee_proportional_millionths: 0,
6251 excess_data: Vec::new()
6252 });
6253
6254 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6256 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6257 short_channel_id: 1,
6258 timestamp: 2,
6259 message_flags: 1, channel_flags: 0,
6261 cltv_expiry_delta: 0,
6262 htlc_minimum_msat: 0,
6263 htlc_maximum_msat: 100_000,
6264 fee_base_msat: 0,
6265 fee_proportional_millionths: 0,
6266 excess_data: Vec::new()
6267 });
6268 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
6269 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6270 short_channel_id: 3,
6271 timestamp: 2,
6272 message_flags: 1, channel_flags: 0,
6274 cltv_expiry_delta: 0,
6275 htlc_minimum_msat: 0,
6276 htlc_maximum_msat: 100_000,
6277 fee_base_msat: 0,
6278 fee_proportional_millionths: 0,
6279 excess_data: Vec::new()
6280 });
6281
6282 add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(16)), 16);
6283 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
6284 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6285 short_channel_id: 16,
6286 timestamp: 2,
6287 message_flags: 1, channel_flags: 0,
6289 cltv_expiry_delta: 0,
6290 htlc_minimum_msat: 0,
6291 htlc_maximum_msat: 100_000,
6292 fee_base_msat: 1_000,
6293 fee_proportional_millionths: 0,
6294 excess_data: Vec::new()
6295 });
6296 update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
6297 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6298 short_channel_id: 16,
6299 timestamp: 2,
6300 message_flags: 1, channel_flags: 3, cltv_expiry_delta: 0,
6303 htlc_minimum_msat: 0,
6304 htlc_maximum_msat: 100_000,
6305 fee_base_msat: 1_000,
6306 fee_proportional_millionths: 0,
6307 excess_data: Vec::new()
6308 });
6309
6310 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6314 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6315 short_channel_id: 12,
6316 timestamp: 2,
6317 message_flags: 1, channel_flags: 0,
6319 cltv_expiry_delta: 0,
6320 htlc_minimum_msat: 0,
6321 htlc_maximum_msat: 100_000,
6322 fee_base_msat: 0,
6323 fee_proportional_millionths: 0,
6324 excess_data: Vec::new()
6325 });
6326 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
6327 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6328 short_channel_id: 13,
6329 timestamp: 2,
6330 message_flags: 1, channel_flags: 0,
6332 cltv_expiry_delta: 0,
6333 htlc_minimum_msat: 0,
6334 htlc_maximum_msat: 100_000,
6335 fee_base_msat: 0,
6336 fee_proportional_millionths: 0,
6337 excess_data: Vec::new()
6338 });
6339
6340 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
6341 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6342 short_channel_id: 6,
6343 timestamp: 2,
6344 message_flags: 1, channel_flags: 0,
6346 cltv_expiry_delta: 0,
6347 htlc_minimum_msat: 0,
6348 htlc_maximum_msat: 200_000,
6349 fee_base_msat: 0,
6350 fee_proportional_millionths: 0,
6351 excess_data: Vec::new()
6352 });
6353 update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
6354 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6355 short_channel_id: 11,
6356 timestamp: 2,
6357 message_flags: 1, channel_flags: 0,
6359 cltv_expiry_delta: 0,
6360 htlc_minimum_msat: 0,
6361 htlc_maximum_msat: 200_000,
6362 fee_base_msat: 0,
6363 fee_proportional_millionths: 0,
6364 excess_data: Vec::new()
6365 });
6366
6367 let route_params = RouteParameters::from_payment_params_and_value(
6372 payment_params, amt);
6373 let res = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6374 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes);
6375 res
6376 }
6377
6378 #[test]
6379 #[rustfmt::skip]
6380 fn fees_on_mpp_route_test() {
6381 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
6385 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
6386 let scorer = ln_test_utils::TestScorer::new();
6387 let random_seed_bytes = [42; 32];
6388 let config = UserConfig::default();
6389 let payment_params = PaymentParameters::from_node_id(nodes[3], 42)
6390 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
6391 .unwrap();
6392
6393 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6404 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6405 short_channel_id: 2,
6406 timestamp: 2,
6407 message_flags: 1, channel_flags: 2,
6409 cltv_expiry_delta: 0,
6410 htlc_minimum_msat: 0,
6411 htlc_maximum_msat: 100_000,
6412 fee_base_msat: 0,
6413 fee_proportional_millionths: 0,
6414 excess_data: Vec::new()
6415 });
6416
6417 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
6418 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6419 short_channel_id: 7,
6420 timestamp: 2,
6421 message_flags: 1, channel_flags: 2,
6423 cltv_expiry_delta: 0,
6424 htlc_minimum_msat: 0,
6425 htlc_maximum_msat: 100_000,
6426 fee_base_msat: 0,
6427 fee_proportional_millionths: 0,
6428 excess_data: Vec::new()
6429 });
6430
6431 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6433 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6434 short_channel_id: 1,
6435 timestamp: 2,
6436 message_flags: 1, channel_flags: 0,
6438 cltv_expiry_delta: 0,
6439 htlc_minimum_msat: 0,
6440 htlc_maximum_msat: 100_000,
6441 fee_base_msat: 0,
6442 fee_proportional_millionths: 0,
6443 excess_data: Vec::new()
6444 });
6445 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
6446 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6447 short_channel_id: 3,
6448 timestamp: 2,
6449 message_flags: 1, channel_flags: 0,
6451 cltv_expiry_delta: 0,
6452 htlc_minimum_msat: 0,
6453 htlc_maximum_msat: 100_000,
6454 fee_base_msat: 0,
6455 fee_proportional_millionths: 0,
6456 excess_data: Vec::new()
6457 });
6458
6459 add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
6460 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
6461 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6462 short_channel_id: 5,
6463 timestamp: 2,
6464 message_flags: 1, channel_flags: 0,
6466 cltv_expiry_delta: 0,
6467 htlc_minimum_msat: 0,
6468 htlc_maximum_msat: 100_000,
6469 fee_base_msat: 0,
6470 fee_proportional_millionths: 0,
6471 excess_data: Vec::new()
6472 });
6473 update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
6474 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6475 short_channel_id: 5,
6476 timestamp: 2,
6477 message_flags: 1, channel_flags: 3, cltv_expiry_delta: 0,
6480 htlc_minimum_msat: 0,
6481 htlc_maximum_msat: 100_000,
6482 fee_base_msat: 0,
6483 fee_proportional_millionths: 0,
6484 excess_data: Vec::new()
6485 });
6486
6487 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6498 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6499 short_channel_id: 12,
6500 timestamp: 2,
6501 message_flags: 1, channel_flags: 0,
6503 cltv_expiry_delta: 0,
6504 htlc_minimum_msat: 0,
6505 htlc_maximum_msat: 250_000,
6506 fee_base_msat: 0,
6507 fee_proportional_millionths: 0,
6508 excess_data: Vec::new()
6509 });
6510 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
6511 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6512 short_channel_id: 13,
6513 timestamp: 2,
6514 message_flags: 1, channel_flags: 0,
6516 cltv_expiry_delta: 0,
6517 htlc_minimum_msat: 0,
6518 htlc_maximum_msat: MAX_VALUE_MSAT,
6519 fee_base_msat: 0,
6520 fee_proportional_millionths: 0,
6521 excess_data: Vec::new()
6522 });
6523
6524 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
6525 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6526 short_channel_id: 6,
6527 timestamp: 2,
6528 message_flags: 1, channel_flags: 0,
6530 cltv_expiry_delta: 0,
6531 htlc_minimum_msat: 0,
6532 htlc_maximum_msat: MAX_VALUE_MSAT,
6533 fee_base_msat: 150_000,
6534 fee_proportional_millionths: 0,
6535 excess_data: Vec::new()
6536 });
6537 update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
6538 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6539 short_channel_id: 11,
6540 timestamp: 2,
6541 message_flags: 1, channel_flags: 0,
6543 cltv_expiry_delta: 0,
6544 htlc_minimum_msat: 0,
6545 htlc_maximum_msat: MAX_VALUE_MSAT,
6546 fee_base_msat: 0,
6547 fee_proportional_millionths: 0,
6548 excess_data: Vec::new()
6549 });
6550
6551 {
6552 let route_params = RouteParameters::from_payment_params_and_value(
6554 payment_params.clone(), 210_000);
6555 if let Err(err) = get_route(
6556 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
6557 &scorer, &Default::default(), &random_seed_bytes) {
6558 assert_eq!(err, "Failed to find a sufficient route to the given destination");
6559 } else { panic!(); }
6560 }
6561
6562 {
6563 let route_params = RouteParameters { payment_params: payment_params.clone(), final_value_msat: 200_000,
6565 max_total_routing_fee_msat: Some(149_999) };
6566 if let Err(err) = get_route(
6567 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
6568 &scorer, &Default::default(), &random_seed_bytes) {
6569 assert_eq!(err, "Failed to find a sufficient route to the given destination");
6570 } else { panic!(); }
6571 }
6572
6573 {
6574 let route_params = RouteParameters { payment_params: payment_params.clone(), final_value_msat: 200_000,
6576 max_total_routing_fee_msat: Some(150_000) };
6577 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6578 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6579 assert_eq!(route.paths.len(), 2);
6580
6581 let mut total_amount_paid_msat = 0;
6582 for path in &route.paths {
6583 assert_eq!(path.hops.last().unwrap().pubkey, nodes[3]);
6584 total_amount_paid_msat += path.final_value_msat();
6585 }
6586 assert_eq!(total_amount_paid_msat, 200_000);
6587 assert_eq!(route.get_total_fees(), 150_000);
6588 }
6589 }
6590
6591 #[test]
6592 #[rustfmt::skip]
6593 fn mpp_with_last_hops() {
6594 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
6608 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
6609 let scorer = ln_test_utils::TestScorer::new();
6610 let random_seed_bytes = [42; 32];
6611 let config = UserConfig::default();
6612 let payment_params = PaymentParameters::from_node_id(PublicKey::from_slice(&[2; 33]).unwrap(), 42)
6613 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap()
6614 .with_route_hints(vec![RouteHint(vec![RouteHintHop {
6615 src_node_id: nodes[2],
6616 short_channel_id: 42,
6617 fees: RoutingFees { base_msat: 0, proportional_millionths: 0 },
6618 cltv_expiry_delta: 42,
6619 htlc_minimum_msat: None,
6620 htlc_maximum_msat: None,
6621 }])]).unwrap().with_max_channel_saturation_power_of_half(0);
6622
6623 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6629 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6630 short_channel_id: 1,
6631 timestamp: 2,
6632 message_flags: 1, channel_flags: 0,
6634 cltv_expiry_delta: (5 << 4) | 5,
6635 htlc_minimum_msat: 0,
6636 htlc_maximum_msat: 99_000,
6637 fee_base_msat: u32::max_value(),
6638 fee_proportional_millionths: u32::max_value(),
6639 excess_data: Vec::new()
6640 });
6641 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6642 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6643 short_channel_id: 2,
6644 timestamp: 2,
6645 message_flags: 1, channel_flags: 0,
6647 cltv_expiry_delta: (5 << 4) | 3,
6648 htlc_minimum_msat: 0,
6649 htlc_maximum_msat: 99_000,
6650 fee_base_msat: u32::max_value(),
6651 fee_proportional_millionths: u32::max_value(),
6652 excess_data: Vec::new()
6653 });
6654 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
6655 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6656 short_channel_id: 4,
6657 timestamp: 2,
6658 message_flags: 1, channel_flags: 0,
6660 cltv_expiry_delta: (4 << 4) | 1,
6661 htlc_minimum_msat: 0,
6662 htlc_maximum_msat: MAX_VALUE_MSAT,
6663 fee_base_msat: 1,
6664 fee_proportional_millionths: 0,
6665 excess_data: Vec::new()
6666 });
6667 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
6668 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6669 short_channel_id: 13,
6670 timestamp: 2,
6671 message_flags: 1, channel_flags: 0|2, cltv_expiry_delta: (13 << 4) | 1,
6674 htlc_minimum_msat: 0,
6675 htlc_maximum_msat: MAX_VALUE_MSAT,
6676 fee_base_msat: 0,
6677 fee_proportional_millionths: 2000000,
6678 excess_data: Vec::new()
6679 });
6680
6681 let route_params = RouteParameters::from_payment_params_and_value(
6684 payment_params, 100_000);
6685 let mut route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6686 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6687 assert_eq!(route.paths.len(), 2);
6688 route.paths.sort_by_key(|path| path.hops[0].short_channel_id);
6689 assert_eq!(route.paths[0].hops[0].short_channel_id, 1);
6693 assert_eq!(route.paths[0].hops[0].fee_msat, 0);
6694 assert_eq!(route.paths[0].hops[2].fee_msat, 99_000);
6695 assert_eq!(route.paths[1].hops[0].short_channel_id, 2);
6696 assert_eq!(route.paths[1].hops[0].fee_msat, 1);
6697 assert_eq!(route.paths[1].hops[2].fee_msat, 1_000);
6698 assert_eq!(route.get_total_fees(), 1);
6699 assert_eq!(route.get_total_amount(), 100_000);
6700 }
6701
6702 #[test]
6703 #[rustfmt::skip]
6704 fn drop_lowest_channel_mpp_route_test() {
6705 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
6708 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
6709 let scorer = ln_test_utils::TestScorer::new();
6710 let random_seed_bytes = [42; 32];
6711 let config = UserConfig::default();
6712 let payment_params = PaymentParameters::from_node_id(nodes[2], 42)
6713 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
6714 .unwrap()
6715 .with_max_channel_saturation_power_of_half(0);
6716
6717 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6728 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6729 short_channel_id: 1,
6730 timestamp: 2,
6731 message_flags: 1, channel_flags: 0,
6733 cltv_expiry_delta: 0,
6734 htlc_minimum_msat: 0,
6735 htlc_maximum_msat: 100_000,
6736 fee_base_msat: 0,
6737 fee_proportional_millionths: 0,
6738 excess_data: Vec::new()
6739 });
6740 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
6741 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6742 short_channel_id: 3,
6743 timestamp: 2,
6744 message_flags: 1, channel_flags: 0,
6746 cltv_expiry_delta: 0,
6747 htlc_minimum_msat: 0,
6748 htlc_maximum_msat: 50_000,
6749 fee_base_msat: 100,
6750 fee_proportional_millionths: 0,
6751 excess_data: Vec::new()
6752 });
6753
6754 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6756 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6757 short_channel_id: 12,
6758 timestamp: 2,
6759 message_flags: 1, channel_flags: 0,
6761 cltv_expiry_delta: 0,
6762 htlc_minimum_msat: 0,
6763 htlc_maximum_msat: 60_000,
6764 fee_base_msat: 100,
6765 fee_proportional_millionths: 0,
6766 excess_data: Vec::new()
6767 });
6768 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
6769 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6770 short_channel_id: 13,
6771 timestamp: 2,
6772 message_flags: 1, channel_flags: 0,
6774 cltv_expiry_delta: 0,
6775 htlc_minimum_msat: 0,
6776 htlc_maximum_msat: 60_000,
6777 fee_base_msat: 0,
6778 fee_proportional_millionths: 0,
6779 excess_data: Vec::new()
6780 });
6781
6782 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
6784 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6785 short_channel_id: 2,
6786 timestamp: 2,
6787 message_flags: 1, channel_flags: 0,
6789 cltv_expiry_delta: 0,
6790 htlc_minimum_msat: 0,
6791 htlc_maximum_msat: 20_000,
6792 fee_base_msat: 0,
6793 fee_proportional_millionths: 0,
6794 excess_data: Vec::new()
6795 });
6796 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
6797 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6798 short_channel_id: 4,
6799 timestamp: 2,
6800 message_flags: 1, channel_flags: 0,
6802 cltv_expiry_delta: 0,
6803 htlc_minimum_msat: 0,
6804 htlc_maximum_msat: 20_000,
6805 fee_base_msat: 0,
6806 fee_proportional_millionths: 0,
6807 excess_data: Vec::new()
6808 });
6809
6810 {
6811 let route_params = RouteParameters::from_payment_params_and_value(
6813 payment_params.clone(), 150_000);
6814 if let Err(err) = get_route(
6815 &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
6816 &scorer, &Default::default(), &random_seed_bytes) {
6817 assert_eq!(err, "Failed to find a sufficient route to the given destination");
6818 } else { panic!(); }
6819 }
6820
6821 {
6822 let route_params = RouteParameters::from_payment_params_and_value(
6825 payment_params.clone(), 125_000);
6826 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6827 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6828 assert_eq!(route.paths.len(), 3);
6829 let mut total_amount_paid_msat = 0;
6830 for path in &route.paths {
6831 assert_eq!(path.hops.len(), 2);
6832 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
6833 total_amount_paid_msat += path.final_value_msat();
6834 }
6835 assert_eq!(total_amount_paid_msat, 125_000);
6836 }
6837
6838 {
6839 let route_params = RouteParameters::from_payment_params_and_value(
6841 payment_params, 90_000);
6842 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
6843 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
6844 assert_eq!(route.paths.len(), 2);
6845 let mut total_amount_paid_msat = 0;
6846 for path in &route.paths {
6847 assert_eq!(path.hops.len(), 2);
6848 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
6849 total_amount_paid_msat += path.final_value_msat();
6850 }
6851 assert_eq!(total_amount_paid_msat, 90_000);
6852 }
6853 }
6854
6855 #[test]
6856 #[rustfmt::skip]
6857 fn min_criteria_consistency() {
6858 let secp_ctx = Secp256k1::new();
6883 let logger = Arc::new(ln_test_utils::TestLogger::new());
6884 let network = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
6885 let gossip_sync = P2PGossipSync::new(Arc::clone(&network), None, Arc::clone(&logger));
6886 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
6887 let scorer = ln_test_utils::TestScorer::new();
6888 let random_seed_bytes = [42; 32];
6889 let payment_params = PaymentParameters::from_node_id(nodes[6], 42);
6890
6891 add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[1], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6);
6892 for (key, channel_flags) in [(&our_privkey, 0), (&privkeys[1], 3)] {
6893 update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6894 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6895 short_channel_id: 6,
6896 timestamp: 1,
6897 message_flags: 1, channel_flags,
6899 cltv_expiry_delta: (6 << 4) | 0,
6900 htlc_minimum_msat: 0,
6901 htlc_maximum_msat: MAX_VALUE_MSAT,
6902 fee_base_msat: 0,
6903 fee_proportional_millionths: 0,
6904 excess_data: Vec::new()
6905 });
6906 }
6907 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[1], NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0);
6908
6909 add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
6910 for (key, channel_flags) in [(&privkeys[1], 0), (&privkeys[4], 3)] {
6911 update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6912 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6913 short_channel_id: 5,
6914 timestamp: 1,
6915 message_flags: 1, channel_flags,
6917 cltv_expiry_delta: (5 << 4) | 0,
6918 htlc_minimum_msat: 0,
6919 htlc_maximum_msat: MAX_VALUE_MSAT,
6920 fee_base_msat: 100,
6921 fee_proportional_millionths: 0,
6922 excess_data: Vec::new()
6923 });
6924 }
6925 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[4], NodeFeatures::from_le_bytes(id_to_feature_flags(4)), 0);
6926
6927 add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), 4);
6928 for (key, channel_flags) in [(&privkeys[4], 0), (&privkeys[3], 3)] {
6929 update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6930 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6931 short_channel_id: 4,
6932 timestamp: 1,
6933 message_flags: 1, channel_flags,
6935 cltv_expiry_delta: (4 << 4) | 0,
6936 htlc_minimum_msat: 0,
6937 htlc_maximum_msat: MAX_VALUE_MSAT,
6938 fee_base_msat: 0,
6939 fee_proportional_millionths: 0,
6940 excess_data: Vec::new()
6941 });
6942 }
6943 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[3], NodeFeatures::from_le_bytes(id_to_feature_flags(3)), 0);
6944
6945 add_channel(&gossip_sync, &secp_ctx, &privkeys[3], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 3);
6946 for (key, channel_flags) in [(&privkeys[3], 0), (&privkeys[2], 3)] {
6947 update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6948 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6949 short_channel_id: 3,
6950 timestamp: 1,
6951 message_flags: 1, channel_flags,
6953 cltv_expiry_delta: (3 << 4) | 0,
6954 htlc_minimum_msat: 0,
6955 htlc_maximum_msat: MAX_VALUE_MSAT,
6956 fee_base_msat: 0,
6957 fee_proportional_millionths: 0,
6958 excess_data: Vec::new()
6959 });
6960 }
6961 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[2], NodeFeatures::from_le_bytes(id_to_feature_flags(2)), 0);
6962
6963 add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), 2);
6964 for (key, channel_flags) in [(&privkeys[2], 0), (&privkeys[4], 3)] {
6965 update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6966 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6967 short_channel_id: 2,
6968 timestamp: 1,
6969 message_flags: 1, channel_flags,
6971 cltv_expiry_delta: (2 << 4) | 0,
6972 htlc_minimum_msat: 0,
6973 htlc_maximum_msat: MAX_VALUE_MSAT,
6974 fee_base_msat: 0,
6975 fee_proportional_millionths: 0,
6976 excess_data: Vec::new()
6977 });
6978 }
6979
6980 add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[6], ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1);
6981 for (key, channel_flags) in [(&privkeys[4], 0), (&privkeys[6], 3)] {
6982 update_channel(&gossip_sync, &secp_ctx, key, UnsignedChannelUpdate {
6983 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
6984 short_channel_id: 1,
6985 timestamp: 1,
6986 message_flags: 1, channel_flags,
6988 cltv_expiry_delta: (1 << 4) | 0,
6989 htlc_minimum_msat: 100,
6990 htlc_maximum_msat: MAX_VALUE_MSAT,
6991 fee_base_msat: 0,
6992 fee_proportional_millionths: 0,
6993 excess_data: Vec::new()
6994 });
6995 }
6996 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[6], NodeFeatures::from_le_bytes(id_to_feature_flags(6)), 0);
6997
6998 {
6999 let route_params = RouteParameters::from_payment_params_and_value(
7001 payment_params, 10_000);
7002 let route = get_route(&our_id, &route_params, &network.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(), 3);
7006
7007 assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
7008 assert_eq!(route.paths[0].hops[0].short_channel_id, 6);
7009 assert_eq!(route.paths[0].hops[0].fee_msat, 100);
7010 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (5 << 4) | 0);
7011 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(1));
7012 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(6));
7013
7014 assert_eq!(route.paths[0].hops[1].pubkey, nodes[4]);
7015 assert_eq!(route.paths[0].hops[1].short_channel_id, 5);
7016 assert_eq!(route.paths[0].hops[1].fee_msat, 0);
7017 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, (1 << 4) | 0);
7018 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(4));
7019 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(5));
7020
7021 assert_eq!(route.paths[0].hops[2].pubkey, nodes[6]);
7022 assert_eq!(route.paths[0].hops[2].short_channel_id, 1);
7023 assert_eq!(route.paths[0].hops[2].fee_msat, 10_000);
7024 assert_eq!(route.paths[0].hops[2].cltv_expiry_delta, 42);
7025 assert_eq!(route.paths[0].hops[2].node_features.le_flags(), &id_to_feature_flags(6));
7026 assert_eq!(route.paths[0].hops[2].channel_features.le_flags(), &id_to_feature_flags(1));
7027 }
7028 }
7029
7030 #[test]
7031 #[rustfmt::skip]
7032 fn exact_fee_liquidity_limit() {
7033 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
7037 let (our_privkey, our_id, _, nodes) = get_nodes(&secp_ctx);
7038 let scorer = ln_test_utils::TestScorer::new();
7039 let random_seed_bytes = [42; 32];
7040 let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
7041
7042 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
7045 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
7046 short_channel_id: 2,
7047 timestamp: 2,
7048 message_flags: 1, channel_flags: 0,
7050 cltv_expiry_delta: 0,
7051 htlc_minimum_msat: 0,
7052 htlc_maximum_msat: 85_000,
7053 fee_base_msat: 0,
7054 fee_proportional_millionths: 0,
7055 excess_data: Vec::new()
7056 });
7057
7058 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
7059 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
7060 short_channel_id: 12,
7061 timestamp: 2,
7062 message_flags: 1, channel_flags: 0,
7064 cltv_expiry_delta: (4 << 4) | 1,
7065 htlc_minimum_msat: 0,
7066 htlc_maximum_msat: 270_000,
7067 fee_base_msat: 0,
7068 fee_proportional_millionths: 1000000,
7069 excess_data: Vec::new()
7070 });
7071
7072 {
7073 let mut route_params = RouteParameters::from_payment_params_and_value(
7076 payment_params, 90_000);
7077 route_params.max_total_routing_fee_msat = Some(90_000*2);
7078 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
7079 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7080 assert_eq!(route.paths.len(), 1);
7081 assert_eq!(route.paths[0].hops.len(), 2);
7082
7083 assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
7084 assert_eq!(route.paths[0].hops[0].short_channel_id, 12);
7085 assert_eq!(route.paths[0].hops[0].fee_msat, 90_000*2);
7086 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (13 << 4) | 1);
7087 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(8));
7088 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(12));
7089
7090 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
7091 assert_eq!(route.paths[0].hops[1].short_channel_id, 13);
7092 assert_eq!(route.paths[0].hops[1].fee_msat, 90_000);
7093 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
7094 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), &id_to_feature_flags(3));
7095 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(13));
7096 }
7097 }
7098
7099 #[test]
7100 #[rustfmt::skip]
7101 fn htlc_max_reduction_below_min() {
7102 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
7107 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
7108 let scorer = ln_test_utils::TestScorer::new();
7109 let random_seed_bytes = [42; 32];
7110 let config = UserConfig::default();
7111 let payment_params = PaymentParameters::from_node_id(nodes[2], 42)
7112 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
7113 .unwrap();
7114
7115 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
7119 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
7120 short_channel_id: 2,
7121 timestamp: 2,
7122 message_flags: 1, channel_flags: 0,
7124 cltv_expiry_delta: 0,
7125 htlc_minimum_msat: 0,
7126 htlc_maximum_msat: 80_000,
7127 fee_base_msat: 0,
7128 fee_proportional_millionths: 0,
7129 excess_data: Vec::new()
7130 });
7131 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
7132 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
7133 short_channel_id: 4,
7134 timestamp: 2,
7135 message_flags: 1, channel_flags: 0,
7137 cltv_expiry_delta: (4 << 4) | 1,
7138 htlc_minimum_msat: 90_000,
7139 htlc_maximum_msat: MAX_VALUE_MSAT,
7140 fee_base_msat: 0,
7141 fee_proportional_millionths: 0,
7142 excess_data: Vec::new()
7143 });
7144
7145 {
7146 let mut route_params = RouteParameters::from_payment_params_and_value(
7150 payment_params, 90_000);
7151 route_params.max_total_routing_fee_msat = Some(90_000*2);
7152 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
7153 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7154 assert_eq!(route.paths.len(), 1);
7155 assert_eq!(route.paths[0].hops.len(), 2);
7156
7157 assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
7158 assert_eq!(route.paths[0].hops[0].short_channel_id, 12);
7159 assert_eq!(route.paths[0].hops[0].fee_msat, 90_000*2);
7160 assert_eq!(route.paths[0].hops[0].cltv_expiry_delta, (13 << 4) | 1);
7161 assert_eq!(route.paths[0].hops[0].node_features.le_flags(), &id_to_feature_flags(8));
7162 assert_eq!(route.paths[0].hops[0].channel_features.le_flags(), &id_to_feature_flags(12));
7163
7164 assert_eq!(route.paths[0].hops[1].pubkey, nodes[2]);
7165 assert_eq!(route.paths[0].hops[1].short_channel_id, 13);
7166 assert_eq!(route.paths[0].hops[1].fee_msat, 90_000);
7167 assert_eq!(route.paths[0].hops[1].cltv_expiry_delta, 42);
7168 assert_eq!(route.paths[0].hops[1].node_features.le_flags(), channelmanager::provided_bolt11_invoice_features(&config).le_flags());
7169 assert_eq!(route.paths[0].hops[1].channel_features.le_flags(), &id_to_feature_flags(13));
7170 }
7171 }
7172
7173 #[test]
7174 #[rustfmt::skip]
7175 fn multiple_direct_first_hops() {
7176 let secp_ctx = Secp256k1::new();
7183 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7184 let logger = Arc::new(ln_test_utils::TestLogger::new());
7185 let network_graph = NetworkGraph::new(Network::Testnet, Arc::clone(&logger));
7186 let scorer = ln_test_utils::TestScorer::new();
7187 let config = UserConfig::default();
7188 let payment_params = PaymentParameters::from_node_id(nodes[0], 42)
7189 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
7190 .unwrap();
7191 let random_seed_bytes = [42; 32];
7192
7193 {
7194 let route_params = RouteParameters::from_payment_params_and_value(
7195 payment_params.clone(), 100_000);
7196 let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[
7197 &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 200_000),
7198 &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 10_000),
7199 ]), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7200 assert_eq!(route.paths.len(), 1);
7201 assert_eq!(route.paths[0].hops.len(), 1);
7202
7203 assert_eq!(route.paths[0].hops[0].pubkey, nodes[0]);
7204 assert_eq!(route.paths[0].hops[0].short_channel_id, 3);
7205 assert_eq!(route.paths[0].hops[0].fee_msat, 100_000);
7206 }
7207 {
7208 let route_params = RouteParameters::from_payment_params_and_value(
7209 payment_params.clone(), 100_000);
7210 let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[
7211 &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7212 &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7213 ]), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7214 assert_eq!(route.paths.len(), 2);
7215 assert_eq!(route.paths[0].hops.len(), 1);
7216 assert_eq!(route.paths[1].hops.len(), 1);
7217
7218 assert!((route.paths[0].hops[0].short_channel_id == 3 && route.paths[1].hops[0].short_channel_id == 2) ||
7219 (route.paths[0].hops[0].short_channel_id == 2 && route.paths[1].hops[0].short_channel_id == 3));
7220
7221 assert_eq!(route.paths[0].hops[0].pubkey, nodes[0]);
7222 assert_eq!(route.paths[0].hops[0].fee_msat, 50_000);
7223
7224 assert_eq!(route.paths[1].hops[0].pubkey, nodes[0]);
7225 assert_eq!(route.paths[1].hops[0].fee_msat, 50_000);
7226 }
7227
7228 {
7229 let route_params = RouteParameters::from_payment_params_and_value(
7237 payment_params, 100_000);
7238 let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[
7239 &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7240 &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7241 &get_channel_details(Some(5), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7242 &get_channel_details(Some(6), nodes[0], channelmanager::provided_init_features(&config), 300_000),
7243 &get_channel_details(Some(7), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7244 &get_channel_details(Some(8), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7245 &get_channel_details(Some(9), nodes[0], channelmanager::provided_init_features(&config), 50_000),
7246 &get_channel_details(Some(4), nodes[0], channelmanager::provided_init_features(&config), 1_000_000),
7247 ]), Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7248 assert_eq!(route.paths.len(), 1);
7249 assert_eq!(route.paths[0].hops.len(), 1);
7250
7251 assert_eq!(route.paths[0].hops[0].pubkey, nodes[0]);
7252 assert_eq!(route.paths[0].hops[0].short_channel_id, 6);
7253 assert_eq!(route.paths[0].hops[0].fee_msat, 100_000);
7254 }
7255 }
7256
7257 #[test]
7258 #[rustfmt::skip]
7259 fn prefers_shorter_route_with_higher_fees() {
7260 let (secp_ctx, network_graph, _, _, logger) = build_graph();
7261 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7262 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap();
7263
7264 let scorer = ln_test_utils::TestScorer::new();
7266 let random_seed_bytes = [42; 32];
7267 let route_params = RouteParameters::from_payment_params_and_value(
7268 payment_params.clone(), 100);
7269 let route = get_route( &our_id, &route_params, &network_graph.read_only(), None,
7270 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7271 let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
7272
7273 assert_eq!(route.get_total_fees(), 100);
7274 assert_eq!(route.get_total_amount(), 100);
7275 assert_eq!(path, vec![2, 4, 6, 11, 8]);
7276
7277 let scorer = FixedPenaltyScorer::with_penalty(100);
7280 let route_params = RouteParameters::from_payment_params_and_value(
7281 payment_params, 100);
7282 let route = get_route( &our_id, &route_params, &network_graph.read_only(), None,
7283 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7284 let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
7285
7286 assert_eq!(route.get_total_fees(), 300);
7287 assert_eq!(route.get_total_amount(), 100);
7288 assert_eq!(path, vec![2, 4, 7, 10]);
7289 }
7290
7291 struct BadChannelScorer {
7292 short_channel_id: u64,
7293 }
7294
7295 #[cfg(c_bindings)]
7296 impl Writeable for BadChannelScorer {
7297 #[rustfmt::skip]
7298 fn write<W: Writer>(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() }
7299 }
7300 impl ScoreLookUp for BadChannelScorer {
7301 type ScoreParams = ();
7302 #[rustfmt::skip]
7303 fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 {
7304 if candidate.short_channel_id() == Some(self.short_channel_id) { u64::max_value() } else { 0 }
7305 }
7306 }
7307
7308 struct BadNodeScorer {
7309 node_id: NodeId,
7310 }
7311
7312 #[cfg(c_bindings)]
7313 impl Writeable for BadNodeScorer {
7314 #[rustfmt::skip]
7315 fn write<W: Writer>(&self, _w: &mut W) -> Result<(), crate::io::Error> { unimplemented!() }
7316 }
7317
7318 impl ScoreLookUp for BadNodeScorer {
7319 type ScoreParams = ();
7320 #[rustfmt::skip]
7321 fn channel_penalty_msat(&self, candidate: &CandidateRouteHop, _: ChannelUsage, _score_params:&Self::ScoreParams) -> u64 {
7322 if candidate.target() == Some(self.node_id) { u64::max_value() } else { 0 }
7323 }
7324 }
7325
7326 #[test]
7327 #[rustfmt::skip]
7328 fn avoids_routing_through_bad_channels_and_nodes() {
7329 let (secp_ctx, network, _, _, logger) = build_graph();
7330 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7331 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap();
7332 let network_graph = network.read_only();
7333
7334 let scorer = ln_test_utils::TestScorer::new();
7336 let random_seed_bytes = [42; 32];
7337 let route_params = RouteParameters::from_payment_params_and_value(
7338 payment_params, 100);
7339 let route = get_route( &our_id, &route_params, &network_graph, None, Arc::clone(&logger),
7340 &scorer, &Default::default(), &random_seed_bytes).unwrap();
7341 let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
7342
7343 assert_eq!(route.get_total_fees(), 100);
7344 assert_eq!(route.get_total_amount(), 100);
7345 assert_eq!(path, vec![2, 4, 6, 11, 8]);
7346
7347 let scorer = BadChannelScorer { short_channel_id: 6 };
7349 let route = get_route( &our_id, &route_params, &network_graph, None, Arc::clone(&logger),
7350 &scorer, &Default::default(), &random_seed_bytes).unwrap();
7351 let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
7352
7353 assert_eq!(route.get_total_fees(), 300);
7354 assert_eq!(route.get_total_amount(), 100);
7355 assert_eq!(path, vec![2, 4, 7, 10]);
7356
7357 let scorer = BadNodeScorer { node_id: NodeId::from_pubkey(&nodes[2]) };
7359 match get_route( &our_id, &route_params, &network_graph, None, Arc::clone(&logger),
7360 &scorer, &Default::default(), &random_seed_bytes) {
7361 Err(err) => {
7362 assert_eq!(err, "Failed to find a path to the given destination");
7363 },
7364 Ok(_) => panic!("Expected error"),
7365 }
7366 }
7367
7368 #[test]
7369 fn total_fees_single_path() {
7370 let route = Route {
7371 paths: vec![Path { hops: vec![
7372 RouteHop {
7373 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
7374 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7375 short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0, maybe_announced_channel: true,
7376 },
7377 RouteHop {
7378 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
7379 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7380 short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0, maybe_announced_channel: true,
7381 },
7382 RouteHop {
7383 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()[..]).unwrap(),
7384 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7385 short_channel_id: 0, fee_msat: 225, cltv_expiry_delta: 0, maybe_announced_channel: true,
7386 },
7387 ], blinded_tail: None }],
7388 route_params: None,
7389 };
7390
7391 assert_eq!(route.get_total_fees(), 250);
7392 assert_eq!(route.get_total_amount(), 225);
7393 }
7394
7395 #[test]
7396 fn total_fees_multi_path() {
7397 let route = Route {
7398 paths: vec![Path { hops: vec![
7399 RouteHop {
7400 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
7401 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7402 short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0, maybe_announced_channel: true,
7403 },
7404 RouteHop {
7405 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
7406 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7407 short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0, maybe_announced_channel: true,
7408 },
7409 ], blinded_tail: None }, Path { hops: vec![
7410 RouteHop {
7411 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
7412 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7413 short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0, maybe_announced_channel: true,
7414 },
7415 RouteHop {
7416 pubkey: PublicKey::from_slice(&<Vec<u8>>::from_hex("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
7417 channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
7418 short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0, maybe_announced_channel: true,
7419 },
7420 ], blinded_tail: None }],
7421 route_params: None,
7422 };
7423
7424 assert_eq!(route.get_total_fees(), 200);
7425 assert_eq!(route.get_total_amount(), 300);
7426 }
7427
7428 #[test]
7429 fn total_empty_route_no_panic() {
7430 let route = Route { paths: Vec::new(), route_params: None };
7434
7435 assert_eq!(route.get_total_fees(), 0);
7436 assert_eq!(route.get_total_amount(), 0);
7437 }
7438
7439 #[test]
7440 #[rustfmt::skip]
7441 fn limits_total_cltv_delta() {
7442 let (secp_ctx, network, _, _, logger) = build_graph();
7443 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7444 let network_graph = network.read_only();
7445
7446 let scorer = ln_test_utils::TestScorer::new();
7447
7448 let feasible_max_total_cltv_delta = 1008;
7450 let feasible_payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap()
7451 .with_max_total_cltv_expiry_delta(feasible_max_total_cltv_delta);
7452 let random_seed_bytes = [42; 32];
7453 let route_params = RouteParameters::from_payment_params_and_value(
7454 feasible_payment_params, 100);
7455 let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
7456 &scorer, &Default::default(), &random_seed_bytes).unwrap();
7457 let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
7458 assert_ne!(path.len(), 0);
7459
7460 let fail_max_total_cltv_delta = 23;
7462 let fail_payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap()
7463 .with_max_total_cltv_expiry_delta(fail_max_total_cltv_delta);
7464 let route_params = RouteParameters::from_payment_params_and_value(
7465 fail_payment_params, 100);
7466 match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
7467 &Default::default(), &random_seed_bytes)
7468 {
7469 Err(err) => {
7470 assert_eq!(err, "Failed to find a path to the given destination");
7471 },
7472 Ok(_) => panic!("Expected error"),
7473 }
7474 }
7475
7476 #[test]
7477 #[rustfmt::skip]
7478 fn avoids_recently_failed_paths() {
7479 let (secp_ctx, network, _, _, logger) = build_graph();
7482 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7483 let network_graph = network.read_only();
7484
7485 let scorer = ln_test_utils::TestScorer::new();
7486 let mut payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap()
7487 .with_max_path_count(1);
7488 let random_seed_bytes = [42; 32];
7489
7490 let route_params = RouteParameters::from_payment_params_and_value(
7493 payment_params.clone(), 100);
7494 assert!(get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
7495 &scorer, &Default::default(), &random_seed_bytes).is_ok());
7496 loop {
7497 let route_params = RouteParameters::from_payment_params_and_value(
7498 payment_params.clone(), 100);
7499 if let Ok(route) = get_route(&our_id, &route_params, &network_graph, None,
7500 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes)
7501 {
7502 for chan in route.paths[0].hops.iter() {
7503 assert!(!payment_params.previously_failed_channels.contains(&chan.short_channel_id));
7504 }
7505 let victim = (u64::from_ne_bytes(random_seed_bytes[0..8].try_into().unwrap()) as usize)
7506 % route.paths[0].hops.len();
7507 payment_params.previously_failed_channels.push(route.paths[0].hops[victim].short_channel_id);
7508 } else { break; }
7509 }
7510 }
7511
7512 #[test]
7513 #[rustfmt::skip]
7514 fn limits_path_length() {
7515 let (secp_ctx, network, _, _, logger) = build_line_graph();
7516 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7517 let network_graph = network.read_only();
7518
7519 let scorer = ln_test_utils::TestScorer::new();
7520 let random_seed_bytes = [42; 32];
7521
7522 let feasible_payment_params = PaymentParameters::from_node_id(nodes[18], 0);
7524 let route_params = RouteParameters::from_payment_params_and_value(
7525 feasible_payment_params, 100);
7526 let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
7527 &scorer, &Default::default(), &random_seed_bytes).unwrap();
7528 let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
7529 assert!(path.len() == MAX_PATH_LENGTH_ESTIMATE.into());
7530
7531 let fail_payment_params = PaymentParameters::from_node_id(nodes[19], 0);
7533 let route_params = RouteParameters::from_payment_params_and_value(
7534 fail_payment_params, 100);
7535 match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
7536 &Default::default(), &random_seed_bytes)
7537 {
7538 Err(err) => {
7539 assert_eq!(err, "Failed to find a path to the given destination");
7540 },
7541 Ok(_) => panic!("Expected error"),
7542 }
7543 }
7544
7545 #[test]
7546 #[rustfmt::skip]
7547 fn adds_and_limits_cltv_offset() {
7548 let (secp_ctx, network_graph, _, _, logger) = build_graph();
7549 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7550
7551 let scorer = ln_test_utils::TestScorer::new();
7552
7553 let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap();
7554 let random_seed_bytes = [42; 32];
7555 let route_params = RouteParameters::from_payment_params_and_value(
7556 payment_params.clone(), 100);
7557 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
7558 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7559 assert_eq!(route.paths.len(), 1);
7560
7561 let cltv_expiry_deltas_before = route.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::<Vec<u32>>();
7562
7563 let mut route_default = route.clone();
7565 add_random_cltv_offset(&mut route_default, &payment_params, &network_graph.read_only(), &random_seed_bytes);
7566 let cltv_expiry_deltas_default = route_default.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::<Vec<u32>>();
7567 assert_eq!(cltv_expiry_deltas_before.split_last().unwrap().1, cltv_expiry_deltas_default.split_last().unwrap().1);
7568 assert!(cltv_expiry_deltas_default.last() > cltv_expiry_deltas_before.last());
7569 assert!(cltv_expiry_deltas_default.last().unwrap() <= &DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA);
7570
7571 let mut route_limited = route.clone();
7573 let limited_max_total_cltv_expiry_delta = cltv_expiry_deltas_before.iter().sum();
7574 let limited_payment_params = payment_params.with_max_total_cltv_expiry_delta(limited_max_total_cltv_expiry_delta);
7575 add_random_cltv_offset(&mut route_limited, &limited_payment_params, &network_graph.read_only(), &random_seed_bytes);
7576 let cltv_expiry_deltas_limited = route_limited.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::<Vec<u32>>();
7577 assert_eq!(cltv_expiry_deltas_before, cltv_expiry_deltas_limited);
7578 }
7579
7580 #[test]
7581 #[rustfmt::skip]
7582 fn adds_plausible_cltv_offset() {
7583 let (secp_ctx, network, _, _, logger) = build_graph();
7584 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7585 let network_graph = network.read_only();
7586 let network_nodes = network_graph.nodes();
7587 let network_channels = network_graph.channels();
7588 let scorer = ln_test_utils::TestScorer::new();
7589 let payment_params = PaymentParameters::from_node_id(nodes[3], 0);
7590 let random_seed_bytes = [42; 32];
7591
7592 let route_params = RouteParameters::from_payment_params_and_value(
7593 payment_params.clone(), 100);
7594 let mut route = get_route(&our_id, &route_params, &network_graph, None,
7595 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
7596 add_random_cltv_offset(&mut route, &payment_params, &network_graph, &random_seed_bytes);
7597
7598 let mut path_plausibility = vec![];
7599
7600 for p in route.paths {
7601 let mut prng = ChaCha20::new(&random_seed_bytes, &[0u8; 12]);
7603 let mut random_bytes = [0u8; ::core::mem::size_of::<usize>()];
7604
7605 prng.process_in_place(&mut random_bytes);
7606 let random_path_index = usize::from_be_bytes(random_bytes).wrapping_rem(p.hops.len());
7607 let observation_point = NodeId::from_pubkey(&p.hops.get(random_path_index).unwrap().pubkey);
7608
7609 let observed_cltv_expiry_delta: u32 = p.hops[random_path_index..].iter().map(|h| h.cltv_expiry_delta).sum();
7611
7612 let mut candidates: VecDeque<(NodeId, Vec<u32>)> = VecDeque::new();
7614 candidates.push_back((observation_point, vec![]));
7615
7616 let mut found_plausible_candidate = false;
7617
7618 'candidate_loop: while let Some((cur_node_id, cur_path_cltv_deltas)) = candidates.pop_front() {
7619 if let Some(remaining) = observed_cltv_expiry_delta.checked_sub(cur_path_cltv_deltas.iter().sum::<u32>()) {
7620 if remaining == 0 || remaining.wrapping_rem(40) == 0 || remaining.wrapping_rem(144) == 0 {
7621 found_plausible_candidate = true;
7622 break 'candidate_loop;
7623 }
7624 }
7625
7626 if let Some(cur_node) = network_nodes.get(&cur_node_id) {
7627 for channel_id in &cur_node.channels {
7628 if let Some(channel_info) = network_channels.get(&channel_id) {
7629 if let Some((dir_info, next_id)) = channel_info.as_directed_from(&cur_node_id) {
7630 let next_cltv_expiry_delta = dir_info.direction().cltv_expiry_delta as u32;
7631 if cur_path_cltv_deltas.iter().sum::<u32>()
7632 .saturating_add(next_cltv_expiry_delta) <= observed_cltv_expiry_delta {
7633 let mut new_path_cltv_deltas = cur_path_cltv_deltas.clone();
7634 new_path_cltv_deltas.push(next_cltv_expiry_delta);
7635 candidates.push_back((*next_id, new_path_cltv_deltas));
7636 }
7637 }
7638 }
7639 }
7640 }
7641 }
7642
7643 path_plausibility.push(found_plausible_candidate);
7644 }
7645 assert!(path_plausibility.iter().all(|x| *x));
7646 }
7647
7648 #[test]
7649 #[rustfmt::skip]
7650 fn builds_correct_path_from_hops() {
7651 let (secp_ctx, network, _, _, logger) = build_graph();
7652 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7653 let network_graph = network.read_only();
7654
7655 let random_seed_bytes = [42; 32];
7656 let payment_params = PaymentParameters::from_node_id(nodes[3], 0);
7657 let hops = [nodes[1], nodes[2], nodes[4], nodes[3]];
7658 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
7659 let route = build_route_from_hops_internal(&our_id, &hops, &route_params, &network_graph,
7660 Arc::clone(&logger), &random_seed_bytes).unwrap();
7661 let route_hop_pubkeys = route.paths[0].hops.iter().map(|hop| hop.pubkey).collect::<Vec<_>>();
7662 assert_eq!(hops.len(), route.paths[0].hops.len());
7663 for (idx, hop_pubkey) in hops.iter().enumerate() {
7664 assert!(*hop_pubkey == route_hop_pubkeys[idx]);
7665 }
7666 }
7667
7668 #[test]
7669 #[rustfmt::skip]
7670 fn avoids_saturating_channels() {
7671 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
7672 let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
7673 let decay_params = ProbabilisticScoringDecayParameters::default();
7674 let scorer = ProbabilisticScorer::new(decay_params, &*network_graph, Arc::clone(&logger));
7675
7676 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
7679 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
7680 short_channel_id: 4,
7681 timestamp: 2,
7682 message_flags: 1, channel_flags: 0,
7684 cltv_expiry_delta: (4 << 4) | 1,
7685 htlc_minimum_msat: 0,
7686 htlc_maximum_msat: 250_000_000,
7687 fee_base_msat: 0,
7688 fee_proportional_millionths: 0,
7689 excess_data: Vec::new()
7690 });
7691 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
7692 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
7693 short_channel_id: 13,
7694 timestamp: 2,
7695 message_flags: 1, channel_flags: 0,
7697 cltv_expiry_delta: (13 << 4) | 1,
7698 htlc_minimum_msat: 0,
7699 htlc_maximum_msat: 250_000_000,
7700 fee_base_msat: 0,
7701 fee_proportional_millionths: 0,
7702 excess_data: Vec::new()
7703 });
7704
7705 let config = UserConfig::default();
7706 let payment_params = PaymentParameters::from_node_id(nodes[2], 42)
7707 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
7708 .unwrap();
7709 let random_seed_bytes = [42; 32];
7710
7711 let route_params = RouteParameters::from_payment_params_and_value(
7716 payment_params, 75_000_000);
7717 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
7718 Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes).unwrap();
7719 assert_eq!(route.paths.len(), 2);
7720 assert!((route.paths[0].hops[1].short_channel_id == 4 && route.paths[1].hops[1].short_channel_id == 13) ||
7721 (route.paths[1].hops[1].short_channel_id == 4 && route.paths[0].hops[1].short_channel_id == 13));
7722 }
7723
7724 pub(super) fn random_init_seed() -> u64 {
7725 use core::hash::{BuildHasher, Hasher};
7727 let seed = std::collections::hash_map::RandomState::new().build_hasher().finish();
7728 println!("Using seed of {}", seed);
7729 seed
7730 }
7731
7732 #[test]
7733 #[rustfmt::skip]
7734 fn generate_routes() {
7735 use crate::routing::scoring::ProbabilisticScoringFeeParameters;
7736
7737 let logger = ln_test_utils::TestLogger::new();
7738 let (graph, mut scorer) = match super::bench_utils::read_graph_scorer(&logger) {
7739 Ok(res) => res,
7740 Err(e) => {
7741 eprintln!("{}", e);
7742 return;
7743 },
7744 };
7745
7746 let params = ProbabilisticScoringFeeParameters::default();
7747 let features = super::Bolt11InvoiceFeatures::empty();
7748
7749 super::bench_utils::generate_test_routes(&graph, &mut scorer, ¶ms, features, random_init_seed(), 0, 2);
7750 }
7751
7752 #[test]
7753 #[rustfmt::skip]
7754 fn generate_routes_mpp() {
7755 use crate::routing::scoring::ProbabilisticScoringFeeParameters;
7756
7757 let logger = ln_test_utils::TestLogger::new();
7758 let (graph, mut scorer) = match super::bench_utils::read_graph_scorer(&logger) {
7759 Ok(res) => res,
7760 Err(e) => {
7761 eprintln!("{}", e);
7762 return;
7763 },
7764 };
7765
7766 let params = ProbabilisticScoringFeeParameters::default();
7767 let features = channelmanager::provided_bolt11_invoice_features(&UserConfig::default());
7768
7769 super::bench_utils::generate_test_routes(&graph, &mut scorer, ¶ms, features, random_init_seed(), 0, 2);
7770 }
7771
7772 #[test]
7773 #[rustfmt::skip]
7774 fn generate_large_mpp_routes() {
7775 use crate::routing::scoring::ProbabilisticScoringFeeParameters;
7776
7777 let logger = ln_test_utils::TestLogger::new();
7778 let (graph, mut scorer) = match super::bench_utils::read_graph_scorer(&logger) {
7779 Ok(res) => res,
7780 Err(e) => {
7781 eprintln!("{}", e);
7782 return;
7783 },
7784 };
7785
7786 let params = ProbabilisticScoringFeeParameters::default();
7787 let features = channelmanager::provided_bolt11_invoice_features(&UserConfig::default());
7788
7789 super::bench_utils::generate_test_routes(&graph, &mut scorer, ¶ms, features, random_init_seed(), 1_000_000, 2);
7790 }
7791
7792 #[test]
7793 #[rustfmt::skip]
7794 fn honors_manual_penalties() {
7795 let (secp_ctx, network_graph, _, _, logger) = build_line_graph();
7796 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7797
7798 let random_seed_bytes = [42; 32];
7799 let mut scorer_params = ProbabilisticScoringFeeParameters::default();
7800 let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), Arc::clone(&network_graph), Arc::clone(&logger));
7801
7802 let usage = ChannelUsage {
7804 amount_msat: 0,
7805 inflight_htlc_msat: 0,
7806 effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_000 },
7807 };
7808 scorer_params.set_manual_penalty(&NodeId::from_pubkey(&nodes[3]), 123);
7809 scorer_params.set_manual_penalty(&NodeId::from_pubkey(&nodes[4]), 456);
7810 let network_graph = network_graph.read_only();
7811 let channels = network_graph.channels();
7812 let channel = channels.get(&5).unwrap();
7813 let info = channel.as_directed_from(&NodeId::from_pubkey(&nodes[3])).unwrap();
7814 let candidate: CandidateRouteHop = CandidateRouteHop::PublicHop(PublicHopCandidate {
7815 info: info.0,
7816 short_channel_id: 5,
7817 });
7818 assert_eq!(scorer.channel_penalty_msat(&candidate, usage, &scorer_params), 456);
7819
7820 let payment_params = PaymentParameters::from_node_id(nodes[10], 42);
7822 let route_params = RouteParameters::from_payment_params_and_value(
7823 payment_params, 100);
7824 let route = get_route(&our_id, &route_params, &network_graph, None,
7825 Arc::clone(&logger), &scorer, &scorer_params, &random_seed_bytes);
7826 assert!(route.is_ok());
7827
7828 scorer_params.add_banned(&NodeId::from_pubkey(&nodes[3]));
7830 let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes);
7831 assert!(route.is_err());
7832
7833 scorer_params.remove_banned(&NodeId::from_pubkey(&nodes[3]));
7835 let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes);
7836 assert!(route.is_ok());
7837 }
7838
7839 #[test]
7840 #[rustfmt::skip]
7841 fn abide_by_route_hint_max_htlc() {
7842 let (secp_ctx, network_graph, _, _, logger) = build_graph();
7845 let netgraph = network_graph.read_only();
7846 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
7847 let scorer = ln_test_utils::TestScorer::new();
7848 let random_seed_bytes = [42; 32];
7849 let config = UserConfig::default();
7850
7851 let max_htlc_msat = 50_000;
7852 let route_hint_1 = RouteHint(vec![RouteHintHop {
7853 src_node_id: nodes[2],
7854 short_channel_id: 42,
7855 fees: RoutingFees {
7856 base_msat: 100,
7857 proportional_millionths: 0,
7858 },
7859 cltv_expiry_delta: 10,
7860 htlc_minimum_msat: None,
7861 htlc_maximum_msat: Some(max_htlc_msat),
7862 }]);
7863 let dest_node_id = ln_test_utils::pubkey(42);
7864 let payment_params = PaymentParameters::from_node_id(dest_node_id, 42)
7865 .with_route_hints(vec![route_hint_1.clone()]).unwrap()
7866 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
7867 .unwrap();
7868
7869 let mut route_params = RouteParameters::from_payment_params_and_value(
7872 payment_params, max_htlc_msat + 1);
7873 route_params.max_total_routing_fee_msat = None;
7874 if let Err(err) = get_route(&our_id,
7875 &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(),
7876 &random_seed_bytes)
7877 {
7878 assert_eq!(err, "Failed to find a sufficient route to the given destination");
7879 } else { panic!(); }
7880
7881 let mut route_hint_2 = route_hint_1.clone();
7883 route_hint_2.0[0].short_channel_id = 43;
7884 let payment_params = PaymentParameters::from_node_id(dest_node_id, 42)
7885 .with_route_hints(vec![route_hint_1, route_hint_2]).unwrap()
7886 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
7887 .unwrap();
7888 let mut route_params = RouteParameters::from_payment_params_and_value(
7889 payment_params, max_htlc_msat + 1);
7890 route_params.max_total_routing_fee_msat = Some(max_htlc_msat * 2);
7891 let route = get_route(&our_id, &route_params, &netgraph, None, Arc::clone(&logger),
7892 &scorer, &Default::default(), &random_seed_bytes).unwrap();
7893 assert_eq!(route.paths.len(), 2);
7894 assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat);
7895 assert!(route.paths[1].hops.last().unwrap().fee_msat <= max_htlc_msat);
7896 }
7897
7898 #[test]
7899 #[rustfmt::skip]
7900 fn direct_channel_to_hints_with_max_htlc() {
7901 let logger = Arc::new(ln_test_utils::TestLogger::new());
7904 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
7905 let scorer = ln_test_utils::TestScorer::new();
7906 let random_seed_bytes = [42; 32];
7907 let config = UserConfig::default();
7908
7909 let our_node_id = ln_test_utils::pubkey(42);
7910 let intermed_node_id = ln_test_utils::pubkey(43);
7911 let first_hop = [get_channel_details(Some(42), intermed_node_id, InitFeatures::from_le_bytes(vec![0b11]), 10_000_000)];
7912
7913 let amt_msat = 900_000;
7914 let max_htlc_msat = 500_000;
7915 let route_hint_1 = RouteHint(vec![RouteHintHop {
7916 src_node_id: intermed_node_id,
7917 short_channel_id: 44,
7918 fees: RoutingFees {
7919 base_msat: 100,
7920 proportional_millionths: 0,
7921 },
7922 cltv_expiry_delta: 10,
7923 htlc_minimum_msat: None,
7924 htlc_maximum_msat: Some(max_htlc_msat),
7925 }, RouteHintHop {
7926 src_node_id: intermed_node_id,
7927 short_channel_id: 45,
7928 fees: RoutingFees {
7929 base_msat: 100,
7930 proportional_millionths: 0,
7931 },
7932 cltv_expiry_delta: 10,
7933 htlc_minimum_msat: None,
7934 htlc_maximum_msat: Some(max_htlc_msat - 50),
7936 }]);
7937 let mut route_hint_2 = route_hint_1.clone();
7938 route_hint_2.0[0].short_channel_id = 46;
7939 route_hint_2.0[1].short_channel_id = 47;
7940 let dest_node_id = ln_test_utils::pubkey(44);
7941 let payment_params = PaymentParameters::from_node_id(dest_node_id, 42)
7942 .with_route_hints(vec![route_hint_1, route_hint_2]).unwrap()
7943 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
7944 .unwrap();
7945
7946 let route_params = RouteParameters::from_payment_params_and_value(
7947 payment_params, amt_msat);
7948 let route = get_route(&our_node_id, &route_params, &network_graph.read_only(),
7949 Some(&first_hop.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
7950 &Default::default(), &random_seed_bytes).unwrap();
7951 assert_eq!(route.paths.len(), 2);
7952 assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat);
7953 assert!(route.paths[1].hops.last().unwrap().fee_msat <= max_htlc_msat);
7954 assert_eq!(route.get_total_amount(), amt_msat);
7955
7956 let first_hops = [
7959 get_channel_details(Some(42), intermed_node_id, InitFeatures::from_le_bytes(vec![0b11]), amt_msat - 10),
7960 get_channel_details(Some(43), intermed_node_id, InitFeatures::from_le_bytes(vec![0b11]), amt_msat - 10),
7961 ];
7962 let route = get_route(&our_node_id, &route_params, &network_graph.read_only(),
7963 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
7964 &Default::default(), &random_seed_bytes).unwrap();
7965 assert_eq!(route.paths.len(), 2);
7966 assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat);
7967 assert!(route.paths[1].hops.last().unwrap().fee_msat <= max_htlc_msat);
7968 assert_eq!(route.get_total_amount(), amt_msat);
7969
7970 let blinded_payinfo = BlindedPayInfo {
7972 fee_base_msat: 100,
7973 fee_proportional_millionths: 0,
7974 htlc_minimum_msat: 1,
7975 htlc_maximum_msat: max_htlc_msat,
7976 cltv_expiry_delta: 10,
7977 features: BlindedHopFeatures::empty(),
7978 };
7979 let blinded_path = dummy_blinded_path(intermed_node_id, blinded_payinfo);
7980 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
7981 let payment_params = PaymentParameters::blinded(vec![
7982 blinded_path.clone(), blinded_path.clone()
7983 ]).with_bolt12_features(bolt12_features).unwrap();
7984 let route_params = RouteParameters::from_payment_params_and_value(
7985 payment_params, amt_msat);
7986 let route = get_route(&our_node_id, &route_params, &network_graph.read_only(),
7987 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
7988 &Default::default(), &random_seed_bytes).unwrap();
7989 assert_eq!(route.paths.len(), 2);
7990 assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat);
7991 assert!(route.paths[1].hops.last().unwrap().fee_msat <= max_htlc_msat);
7992 assert_eq!(route.get_total_amount(), amt_msat);
7993 }
7994
7995 #[test]
7996 #[rustfmt::skip]
7997 fn blinded_route_ser() {
7998 let mut route = Route { paths: vec![Path {
8000 hops: vec![RouteHop {
8001 pubkey: ln_test_utils::pubkey(50),
8002 node_features: NodeFeatures::empty(),
8003 short_channel_id: 42,
8004 channel_features: ChannelFeatures::empty(),
8005 fee_msat: 100,
8006 cltv_expiry_delta: 0,
8007 maybe_announced_channel: true,
8008 }],
8009 blinded_tail: Some(BlindedTail {
8010 trampoline_hops: vec![],
8011 hops: vec![
8012 BlindedHop { blinded_node_id: ln_test_utils::pubkey(44), encrypted_payload: Vec::new() },
8013 BlindedHop { blinded_node_id: ln_test_utils::pubkey(45), encrypted_payload: Vec::new() }
8014 ],
8015 blinding_point: ln_test_utils::pubkey(43),
8016 excess_final_cltv_expiry_delta: 40,
8017 final_value_msat: 100,
8018 })}, Path {
8019 hops: vec![RouteHop {
8020 pubkey: ln_test_utils::pubkey(51),
8021 node_features: NodeFeatures::empty(),
8022 short_channel_id: 43,
8023 channel_features: ChannelFeatures::empty(),
8024 fee_msat: 100,
8025 cltv_expiry_delta: 0,
8026 maybe_announced_channel: true,
8027 }], blinded_tail: None }],
8028 route_params: None,
8029 };
8030 let encoded_route = route.encode();
8031 let decoded_route: Route = Readable::read(&mut Cursor::new(&encoded_route[..])).unwrap();
8032 assert_eq!(decoded_route.paths[0].blinded_tail, route.paths[0].blinded_tail);
8033 assert_eq!(decoded_route.paths[1].blinded_tail, route.paths[1].blinded_tail);
8034
8035 route.paths[1].blinded_tail = Some(BlindedTail {
8037 trampoline_hops: vec![],
8038 hops: vec![
8039 BlindedHop { blinded_node_id: ln_test_utils::pubkey(48), encrypted_payload: Vec::new() },
8040 BlindedHop { blinded_node_id: ln_test_utils::pubkey(49), encrypted_payload: Vec::new() }
8041 ],
8042 blinding_point: ln_test_utils::pubkey(47),
8043 excess_final_cltv_expiry_delta: 41,
8044 final_value_msat: 101,
8045 });
8046 let encoded_route = route.encode();
8047 let decoded_route: Route = Readable::read(&mut Cursor::new(&encoded_route[..])).unwrap();
8048 assert_eq!(decoded_route.paths[0].blinded_tail, route.paths[0].blinded_tail);
8049 assert_eq!(decoded_route.paths[1].blinded_tail, route.paths[1].blinded_tail);
8050 }
8051
8052 #[test]
8053 #[rustfmt::skip]
8054 fn blinded_path_inflight_processing() {
8055 let mut inflight_htlcs = InFlightHtlcs::new();
8058 let path = Path {
8059 hops: vec![RouteHop {
8060 pubkey: ln_test_utils::pubkey(42),
8061 node_features: NodeFeatures::empty(),
8062 short_channel_id: 42,
8063 channel_features: ChannelFeatures::empty(),
8064 fee_msat: 100,
8065 cltv_expiry_delta: 0,
8066 maybe_announced_channel: false,
8067 },
8068 RouteHop {
8069 pubkey: ln_test_utils::pubkey(43),
8070 node_features: NodeFeatures::empty(),
8071 short_channel_id: 43,
8072 channel_features: ChannelFeatures::empty(),
8073 fee_msat: 1,
8074 cltv_expiry_delta: 0,
8075 maybe_announced_channel: false,
8076 }],
8077 blinded_tail: Some(BlindedTail {
8078 trampoline_hops: vec![],
8079 hops: vec![BlindedHop { blinded_node_id: ln_test_utils::pubkey(49), encrypted_payload: Vec::new() }],
8080 blinding_point: ln_test_utils::pubkey(48),
8081 excess_final_cltv_expiry_delta: 0,
8082 final_value_msat: 200,
8083 }),
8084 };
8085 inflight_htlcs.process_path(&path, ln_test_utils::pubkey(44));
8086 assert_eq!(*inflight_htlcs.0.get(&(42, true)).unwrap(), 301);
8087 assert_eq!(*inflight_htlcs.0.get(&(43, false)).unwrap(), 201);
8088 }
8089
8090 #[test]
8091 #[rustfmt::skip]
8092 fn blinded_path_cltv_shadow_offset() {
8093 let mut route = Route { paths: vec![Path {
8095 hops: vec![RouteHop {
8096 pubkey: ln_test_utils::pubkey(42),
8097 node_features: NodeFeatures::empty(),
8098 short_channel_id: 42,
8099 channel_features: ChannelFeatures::empty(),
8100 fee_msat: 100,
8101 cltv_expiry_delta: 0,
8102 maybe_announced_channel: false,
8103 },
8104 RouteHop {
8105 pubkey: ln_test_utils::pubkey(43),
8106 node_features: NodeFeatures::empty(),
8107 short_channel_id: 43,
8108 channel_features: ChannelFeatures::empty(),
8109 fee_msat: 1,
8110 cltv_expiry_delta: 0,
8111 maybe_announced_channel: false,
8112 }
8113 ],
8114 blinded_tail: Some(BlindedTail {
8115 trampoline_hops: vec![],
8116 hops: vec![
8117 BlindedHop { blinded_node_id: ln_test_utils::pubkey(45), encrypted_payload: Vec::new() },
8118 BlindedHop { blinded_node_id: ln_test_utils::pubkey(46), encrypted_payload: Vec::new() }
8119 ],
8120 blinding_point: ln_test_utils::pubkey(44),
8121 excess_final_cltv_expiry_delta: 0,
8122 final_value_msat: 200,
8123 }),
8124 }], route_params: None};
8125
8126 let payment_params = PaymentParameters::from_node_id(ln_test_utils::pubkey(47), 18);
8127 let (_, network_graph, _, _, _) = build_line_graph();
8128 add_random_cltv_offset(&mut route, &payment_params, &network_graph.read_only(), &[0; 32]);
8129 assert_eq!(route.paths[0].blinded_tail.as_ref().unwrap().excess_final_cltv_expiry_delta, 40);
8130 assert_eq!(route.paths[0].hops.last().unwrap().cltv_expiry_delta, 40);
8131 }
8132
8133 #[test]
8134 fn simple_blinded_route_hints() {
8135 do_simple_blinded_route_hints(1);
8136 do_simple_blinded_route_hints(2);
8137 do_simple_blinded_route_hints(3);
8138 }
8139
8140 #[rustfmt::skip]
8141 fn do_simple_blinded_route_hints(num_blinded_hops: usize) {
8142 let (secp_ctx, network, _, _, logger) = build_graph();
8144 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8145 let network_graph = network.read_only();
8146
8147 let scorer = ln_test_utils::TestScorer::new();
8148 let random_seed_bytes = [42; 32];
8149
8150 let mut blinded_hops = Vec::new();
8151 for i in 0..num_blinded_hops {
8152 blinded_hops.push(
8153 BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 + i as u8), encrypted_payload: Vec::new() },
8154 );
8155 }
8156 let blinded_payinfo = BlindedPayInfo {
8157 fee_base_msat: 100,
8158 fee_proportional_millionths: 500,
8159 htlc_minimum_msat: 1000,
8160 htlc_maximum_msat: 100_000_000,
8161 cltv_expiry_delta: 15,
8162 features: BlindedHopFeatures::empty(),
8163 };
8164 let blinded_path = BlindedPaymentPath::from_blinded_path_and_payinfo(
8165 nodes[2], ln_test_utils::pubkey(42), blinded_hops, blinded_payinfo.clone()
8166 );
8167 let payment_params = PaymentParameters::blinded(vec![blinded_path.clone(), blinded_path.clone()]);
8168
8169 let encoded_params = payment_params.encode();
8171 let mut s = Cursor::new(&encoded_params);
8172 let mut reader = FixedLengthReader::new(&mut s, encoded_params.len() as u64);
8173 let decoded_params: PaymentParameters = ReadableArgs::read(&mut reader, 42).unwrap();
8174 assert_eq!(payment_params, decoded_params);
8175
8176 let route_params = RouteParameters::from_payment_params_and_value(
8177 payment_params, 1001);
8178 let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
8179 &scorer, &Default::default(), &random_seed_bytes).unwrap();
8180 assert_eq!(route.paths.len(), 1);
8181 assert_eq!(route.paths[0].hops.len(), 2);
8182
8183 let tail = route.paths[0].blinded_tail.as_ref().unwrap();
8184 assert_eq!(&tail.hops, blinded_path.blinded_hops());
8185 assert_eq!(tail.excess_final_cltv_expiry_delta, 0);
8186 assert_eq!(tail.final_value_msat, 1001);
8187
8188 let final_hop = route.paths[0].hops.last().unwrap();
8189 assert_eq!(
8190 NodeId::from_pubkey(&final_hop.pubkey),
8191 *blinded_path.public_introduction_node_id(&network_graph).unwrap()
8192 );
8193 if tail.hops.len() > 1 {
8194 assert_eq!(final_hop.fee_msat,
8195 blinded_payinfo.fee_base_msat as u64 + blinded_payinfo.fee_proportional_millionths as u64 * tail.final_value_msat / 1000000);
8196 assert_eq!(final_hop.cltv_expiry_delta, blinded_payinfo.cltv_expiry_delta as u32);
8197 } else {
8198 assert_eq!(final_hop.fee_msat, 0);
8199 assert_eq!(final_hop.cltv_expiry_delta, 0);
8200 }
8201 }
8202
8203 #[test]
8204 #[rustfmt::skip]
8205 fn blinded_path_routing_errors() {
8206 let (secp_ctx, network, _, _, logger) = build_graph();
8208 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8209 let network_graph = network.read_only();
8210
8211 let scorer = ln_test_utils::TestScorer::new();
8212 let random_seed_bytes = [42; 32];
8213
8214 let blinded_payinfo = BlindedPayInfo {
8215 fee_base_msat: 100,
8216 fee_proportional_millionths: 500,
8217 htlc_minimum_msat: 1000,
8218 htlc_maximum_msat: 100_000_000,
8219 cltv_expiry_delta: 15,
8220 features: BlindedHopFeatures::empty(),
8221 };
8222
8223 let invalid_blinded_path_2 = dummy_one_hop_blinded_path(nodes[2], blinded_payinfo.clone());
8224 let invalid_blinded_path_3 = dummy_one_hop_blinded_path(nodes[3], blinded_payinfo.clone());
8225 let payment_params = PaymentParameters::blinded(vec![
8226 invalid_blinded_path_2, invalid_blinded_path_3]);
8227 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001);
8228 match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
8229 &scorer, &Default::default(), &random_seed_bytes)
8230 {
8231 Err(err) => {
8232 assert_eq!(err, "1-hop blinded paths must all have matching introduction node ids");
8233 },
8234 _ => panic!("Expected error")
8235 }
8236
8237 let invalid_blinded_path = dummy_blinded_path(our_id, blinded_payinfo.clone());
8238 let payment_params = PaymentParameters::blinded(vec![invalid_blinded_path]);
8239 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001);
8240 match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
8241 &Default::default(), &random_seed_bytes)
8242 {
8243 Err(err) => {
8244 assert_eq!(err, "Cannot generate a route to blinded paths if we are the introduction node to all of them");
8245 },
8246 _ => panic!("Expected error")
8247 }
8248
8249 let mut invalid_blinded_path = dummy_one_hop_blinded_path(ln_test_utils::pubkey(46), blinded_payinfo);
8250 invalid_blinded_path.clear_blinded_hops();
8251 let payment_params = PaymentParameters::blinded(vec![invalid_blinded_path]);
8252 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001);
8253 match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
8254 &Default::default(), &random_seed_bytes)
8255 {
8256 Err(err) => {
8257 assert_eq!(err, "0-hop blinded path provided");
8258 },
8259 _ => panic!("Expected error")
8260 }
8261 }
8262
8263 #[test]
8264 #[rustfmt::skip]
8265 fn matching_intro_node_paths_provided() {
8266 let (secp_ctx, network, _, _, logger) = build_graph();
8269 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8270 let network_graph = network.read_only();
8271
8272 let scorer = ln_test_utils::TestScorer::new();
8273 let random_seed_bytes = [42; 32];
8274 let config = UserConfig::default();
8275
8276 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8277 let blinded_payinfo_1 = BlindedPayInfo {
8278 fee_base_msat: 0,
8279 fee_proportional_millionths: 0,
8280 htlc_minimum_msat: 0,
8281 htlc_maximum_msat: 30_000,
8282 cltv_expiry_delta: 0,
8283 features: BlindedHopFeatures::empty(),
8284 };
8285 let blinded_path_1 = dummy_blinded_path(nodes[2], blinded_payinfo_1.clone());
8286
8287 let mut blinded_payinfo_2 = blinded_payinfo_1;
8288 blinded_payinfo_2.htlc_maximum_msat = 70_000;
8289 let blinded_path_2 = BlindedPaymentPath::from_blinded_path_and_payinfo(
8290 nodes[2],
8291 ln_test_utils::pubkey(43),
8292 vec![
8293 BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() },
8294 BlindedHop { blinded_node_id: ln_test_utils::pubkey(42 as u8), encrypted_payload: Vec::new() }
8295 ],
8296 blinded_payinfo_2
8297 );
8298
8299 let blinded_hints = vec![blinded_path_1.clone(), blinded_path_2.clone()];
8300 let payment_params = PaymentParameters::blinded(blinded_hints.clone())
8301 .with_bolt12_features(bolt12_features).unwrap();
8302
8303 let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 100_000);
8304 route_params.max_total_routing_fee_msat = Some(100_000);
8305 let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
8306 &scorer, &Default::default(), &random_seed_bytes).unwrap();
8307 assert_eq!(route.paths.len(), 2);
8308 let mut total_amount_paid_msat = 0;
8309 for path in route.paths.into_iter() {
8310 assert_eq!(path.hops.last().unwrap().pubkey, nodes[2]);
8311 if let Some(bt) = &path.blinded_tail {
8312 assert_eq!(bt.blinding_point,
8313 blinded_hints.iter().find(|p| p.payinfo.htlc_maximum_msat == path.final_value_msat())
8314 .map(|bp| bp.blinding_point()).unwrap());
8315 } else { panic!(); }
8316 total_amount_paid_msat += path.final_value_msat();
8317 }
8318 assert_eq!(total_amount_paid_msat, 100_000);
8319 }
8320
8321 #[test]
8322 #[rustfmt::skip]
8323 fn direct_to_intro_node() {
8324 let secp_ctx = Secp256k1::new();
8334 let logger = Arc::new(ln_test_utils::TestLogger::new());
8335 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8336 let gossip_sync = P2PGossipSync::new(Arc::clone(&network_graph), None, Arc::clone(&logger));
8337 let scorer = ln_test_utils::TestScorer::new();
8338 let random_seed_bytes = [42; 32];
8339
8340 let amt_msat = 10_000_000;
8341 let (_, _, privkeys, nodes) = get_nodes(&secp_ctx);
8342 add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[1],
8343 ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1);
8344 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
8345 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8346 short_channel_id: 1,
8347 timestamp: 1,
8348 message_flags: 1, channel_flags: 0,
8350 cltv_expiry_delta: 42,
8351 htlc_minimum_msat: 1_000,
8352 htlc_maximum_msat: 10_000_000,
8353 fee_base_msat: 800,
8354 fee_proportional_millionths: 0,
8355 excess_data: Vec::new()
8356 });
8357 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
8358 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8359 short_channel_id: 1,
8360 timestamp: 1,
8361 message_flags: 1, channel_flags: 1,
8363 cltv_expiry_delta: 42,
8364 htlc_minimum_msat: 1_000,
8365 htlc_maximum_msat: 10_000_000,
8366 fee_base_msat: 800,
8367 fee_proportional_millionths: 0,
8368 excess_data: Vec::new()
8369 });
8370 let first_hops = [
8371 get_channel_details(Some(1), nodes[1], InitFeatures::from_le_bytes(vec![0b11]), 10_000_000)
8372 ];
8373
8374 let blinded_payinfo = BlindedPayInfo {
8375 fee_base_msat: 1000,
8376 fee_proportional_millionths: 0,
8377 htlc_minimum_msat: 1000,
8378 htlc_maximum_msat: MAX_VALUE_MSAT,
8379 cltv_expiry_delta: 0,
8380 features: BlindedHopFeatures::empty(),
8381 };
8382 let blinded_path = dummy_blinded_path(nodes[1], blinded_payinfo.clone());
8383 let blinded_hints = vec![blinded_path];
8384
8385 let payment_params = PaymentParameters::blinded(blinded_hints.clone());
8386
8387 let netgraph = network_graph.read_only();
8388 let route_params = RouteParameters::from_payment_params_and_value(
8389 payment_params.clone(), amt_msat);
8390 if let Err(err) = get_route(&nodes[0], &route_params, &netgraph,
8391 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
8392 &Default::default(), &random_seed_bytes) {
8393 assert_eq!(err, "Failed to find a path to the given destination");
8394 } else { panic!("Expected error") }
8395
8396 let amt_minus_blinded_path_fee = amt_msat - blinded_payinfo.fee_base_msat as u64;
8398 let route_params = RouteParameters::from_payment_params_and_value(
8399 payment_params, amt_minus_blinded_path_fee);
8400 let route = get_route(&nodes[0], &route_params, &netgraph,
8401 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
8402 &Default::default(), &random_seed_bytes).unwrap();
8403 assert_eq!(route.get_total_fees(), blinded_payinfo.fee_base_msat as u64);
8404 assert_eq!(route.get_total_amount(), amt_minus_blinded_path_fee);
8405 }
8406
8407 #[test]
8408 #[rustfmt::skip]
8409 fn direct_to_matching_intro_nodes() {
8410 let secp_ctx = Secp256k1::new();
8423 let logger = Arc::new(ln_test_utils::TestLogger::new());
8424 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8425 let scorer = ln_test_utils::TestScorer::new();
8426 let random_seed_bytes = [42; 32];
8427 let config = UserConfig::default();
8428
8429 let amt_msat = 21_7020_5185_1403_2640;
8431 let (_, _, _, nodes) = get_nodes(&secp_ctx);
8432 let first_hops = [
8433 get_channel_details(Some(1), nodes[1], channelmanager::provided_init_features(&config),
8434 18446744073709551615),
8435 ];
8436
8437 let blinded_payinfo = BlindedPayInfo {
8438 fee_base_msat: 5046_2720,
8439 fee_proportional_millionths: 0,
8440 htlc_minimum_msat: 4503_5996_2737_0496,
8441 htlc_maximum_msat: 45_0359_9627_3704_9600,
8442 cltv_expiry_delta: 0,
8443 features: BlindedHopFeatures::empty(),
8444 };
8445 let blinded_path = dummy_blinded_path(nodes[1], blinded_payinfo.clone());
8446 let mut blinded_hints = vec![blinded_path.clone(), blinded_path.clone()];
8447 blinded_hints[1].payinfo.fee_base_msat = 419_4304;
8448 blinded_hints[1].payinfo.fee_proportional_millionths = 257;
8449 blinded_hints[1].payinfo.htlc_minimum_msat = 280_8908_6115_8400;
8450 blinded_hints[1].payinfo.htlc_maximum_msat = 2_8089_0861_1584_0000;
8451 blinded_hints[1].payinfo.cltv_expiry_delta = 0;
8452
8453 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8454 let payment_params = PaymentParameters::blinded(blinded_hints.clone())
8455 .with_bolt12_features(bolt12_features).unwrap();
8456
8457 let netgraph = network_graph.read_only();
8458 let route_params = RouteParameters::from_payment_params_and_value(
8459 payment_params, amt_msat);
8460 let route = get_route(&nodes[0], &route_params, &netgraph,
8461 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
8462 &Default::default(), &random_seed_bytes).unwrap();
8463 assert_eq!(route.get_total_fees(), blinded_payinfo.fee_base_msat as u64);
8464 assert_eq!(route.get_total_amount(), amt_msat);
8465 }
8466
8467 #[test]
8468 #[rustfmt::skip]
8469 fn we_are_intro_node_candidate_hops() {
8470 let (secp_ctx, network_graph, _, _, logger) = build_graph();
8475 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8476 let scorer = ln_test_utils::TestScorer::new();
8477 let random_seed_bytes = [42; 32];
8478 let config = UserConfig::default();
8479
8480 let amt_msat = 21_7020_5185_1423_0019;
8482
8483 let blinded_payinfo = BlindedPayInfo {
8484 fee_base_msat: 5052_9027,
8485 fee_proportional_millionths: 0,
8486 htlc_minimum_msat: 21_7020_5185_1423_0019,
8487 htlc_maximum_msat: 1844_6744_0737_0955_1615,
8488 cltv_expiry_delta: 0,
8489 features: BlindedHopFeatures::empty(),
8490 };
8491 let blinded_path = dummy_blinded_path(our_id, blinded_payinfo.clone());
8492 let mut blinded_hints = vec![blinded_path.clone(), blinded_path.clone()];
8493 blinded_hints[1] = dummy_blinded_path(nodes[6], blinded_payinfo);
8494
8495 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8496 let payment_params = PaymentParameters::blinded(blinded_hints.clone())
8497 .with_bolt12_features(bolt12_features.clone()).unwrap();
8498
8499 let netgraph = network_graph.read_only();
8500 let route_params = RouteParameters::from_payment_params_and_value(
8501 payment_params, amt_msat);
8502 if let Err(err) = get_route(
8503 &our_id, &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes
8504 ) {
8505 assert_eq!(err, "Failed to find a path to the given destination");
8506 } else { panic!() }
8507 }
8508
8509 #[test]
8510 #[rustfmt::skip]
8511 fn we_are_intro_node_bp_in_final_path_fee_calc() {
8512 let (secp_ctx, network_graph, _, _, logger) = build_graph();
8517 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8518 let scorer = ln_test_utils::TestScorer::new();
8519 let random_seed_bytes = [42; 32];
8520 let config = UserConfig::default();
8521
8522 let amt_msat = 21_7020_5185_1423_0019;
8524
8525 let blinded_payinfo = BlindedPayInfo {
8526 fee_base_msat: 10_4425_1395,
8527 fee_proportional_millionths: 0,
8528 htlc_minimum_msat: 21_7301_9934_9094_0931,
8529 htlc_maximum_msat: 1844_6744_0737_0955_1615,
8530 cltv_expiry_delta: 0,
8531 features: BlindedHopFeatures::empty(),
8532 };
8533 let blinded_path = dummy_blinded_path(our_id, blinded_payinfo.clone());
8534 let mut blinded_hints = vec![
8535 blinded_path.clone(), blinded_path.clone(), blinded_path.clone(),
8536 ];
8537 blinded_hints[1].payinfo.fee_base_msat = 5052_9027;
8538 blinded_hints[1].payinfo.htlc_minimum_msat = 21_7020_5185_1423_0019;
8539 blinded_hints[1].payinfo.htlc_maximum_msat = 1844_6744_0737_0955_1615;
8540
8541 blinded_hints[2] = dummy_blinded_path(nodes[6], blinded_payinfo);
8542
8543 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8544 let payment_params = PaymentParameters::blinded(blinded_hints.clone())
8545 .with_bolt12_features(bolt12_features.clone()).unwrap();
8546
8547 let netgraph = network_graph.read_only();
8548 let route_params = RouteParameters::from_payment_params_and_value(
8549 payment_params, amt_msat);
8550 if let Err(err) = get_route(
8551 &our_id, &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes
8552 ) {
8553 assert_eq!(err, "Failed to find a path to the given destination");
8554 } else { panic!() }
8555 }
8556
8557 #[test]
8558 fn min_htlc_overpay_violates_max_htlc() {
8559 do_min_htlc_overpay_violates_max_htlc(true);
8560 do_min_htlc_overpay_violates_max_htlc(false);
8561 }
8562 #[rustfmt::skip]
8563 fn do_min_htlc_overpay_violates_max_htlc(blinded_payee: bool) {
8564 let secp_ctx = Secp256k1::new();
8569 let logger = Arc::new(ln_test_utils::TestLogger::new());
8570 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8571 let scorer = ln_test_utils::TestScorer::new();
8572 let random_seed_bytes = [42; 32];
8573 let config = UserConfig::default();
8574
8575 let amt_msat = 7_4009_8048;
8577 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8578 let first_hop_outbound_capacity = 2_7345_2000;
8579 let first_hops = [get_channel_details(
8580 Some(200), nodes[0], channelmanager::provided_init_features(&config),
8581 first_hop_outbound_capacity
8582 )];
8583
8584 let base_fee = 1_6778_3453;
8585 let htlc_min = 2_5165_8240;
8586 let payment_params = if blinded_payee {
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 * 1000,
8592 cltv_expiry_delta: 0,
8593 features: BlindedHopFeatures::empty(),
8594 };
8595 let blinded_path = dummy_blinded_path(nodes[0], blinded_payinfo);
8596 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8597 PaymentParameters::blinded(vec![blinded_path])
8598 .with_bolt12_features(bolt12_features.clone()).unwrap()
8599 } else {
8600 let route_hint = RouteHint(vec![RouteHintHop {
8601 src_node_id: nodes[0],
8602 short_channel_id: 42,
8603 fees: RoutingFees {
8604 base_msat: base_fee,
8605 proportional_millionths: 0,
8606 },
8607 cltv_expiry_delta: 10,
8608 htlc_minimum_msat: Some(htlc_min),
8609 htlc_maximum_msat: None,
8610 }]);
8611
8612 PaymentParameters::from_node_id(nodes[1], 42)
8613 .with_route_hints(vec![route_hint]).unwrap()
8614 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap()
8615 };
8616
8617 let netgraph = network_graph.read_only();
8618 let route_params = RouteParameters::from_payment_params_and_value(
8619 payment_params, amt_msat);
8620 if let Err(err) = get_route(
8621 &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::<Vec<_>>()),
8622 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes
8623 ) {
8624 assert_eq!(err, "Failed to find a path to the given destination");
8625 } else { panic!() }
8626 }
8627
8628 #[test]
8629 #[rustfmt::skip]
8630 fn previously_used_liquidity_violates_max_htlc() {
8631 do_previously_used_liquidity_violates_max_htlc(true);
8632 do_previously_used_liquidity_violates_max_htlc(false);
8633
8634 }
8635 #[rustfmt::skip]
8636 fn do_previously_used_liquidity_violates_max_htlc(blinded_payee: bool) {
8637 let secp_ctx = Secp256k1::new();
8643 let logger = Arc::new(ln_test_utils::TestLogger::new());
8644 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8645 let scorer = ln_test_utils::TestScorer::new();
8646 let random_seed_bytes = [42; 32];
8647 let config = UserConfig::default();
8648
8649 let amt_msat = 52_4288;
8651 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8652 let first_hops = [get_channel_details(
8653 Some(161), nodes[0], channelmanager::provided_init_features(&config), 486_4000
8654 ), get_channel_details(
8655 Some(122), nodes[0], channelmanager::provided_init_features(&config), 179_5000
8656 )];
8657
8658 let base_fees = [0, 425_9840, 0, 0];
8659 let htlc_mins = [1_4392, 19_7401, 1027, 6_5535];
8660 let payment_params = if blinded_payee {
8661 let mut blinded_hints = Vec::new();
8662 for (base_fee, htlc_min) in base_fees.iter().zip(htlc_mins.iter()) {
8663 let blinded_payinfo = BlindedPayInfo {
8664 fee_base_msat: *base_fee,
8665 fee_proportional_millionths: 0,
8666 htlc_minimum_msat: *htlc_min,
8667 htlc_maximum_msat: htlc_min * 100,
8668 cltv_expiry_delta: 10,
8669 features: BlindedHopFeatures::empty(),
8670 };
8671 blinded_hints.push(dummy_blinded_path(nodes[0], blinded_payinfo));
8672 }
8673 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8674 PaymentParameters::blinded(blinded_hints.clone())
8675 .with_bolt12_features(bolt12_features.clone()).unwrap()
8676 } else {
8677 let mut route_hints = Vec::new();
8678 for (idx, (base_fee, htlc_min)) in base_fees.iter().zip(htlc_mins.iter()).enumerate() {
8679 route_hints.push(RouteHint(vec![RouteHintHop {
8680 src_node_id: nodes[0],
8681 short_channel_id: 42 + idx as u64,
8682 fees: RoutingFees {
8683 base_msat: *base_fee,
8684 proportional_millionths: 0,
8685 },
8686 cltv_expiry_delta: 10,
8687 htlc_minimum_msat: Some(*htlc_min),
8688 htlc_maximum_msat: Some(htlc_min * 100),
8689 }]));
8690 }
8691 PaymentParameters::from_node_id(nodes[1], 42)
8692 .with_route_hints(route_hints).unwrap()
8693 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap()
8694 };
8695
8696 let netgraph = network_graph.read_only();
8697 let route_params = RouteParameters::from_payment_params_and_value(
8698 payment_params, amt_msat);
8699
8700 let route = get_route(
8701 &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::<Vec<_>>()),
8702 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes
8703 ).unwrap();
8704 assert_eq!(route.paths.len(), 1);
8705 assert_eq!(route.get_total_amount(), amt_msat);
8706 }
8707
8708 #[test]
8709 #[rustfmt::skip]
8710 fn candidate_path_min() {
8711 let secp_ctx = Secp256k1::new();
8717 let logger = Arc::new(ln_test_utils::TestLogger::new());
8718 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8719 let gossip_sync = P2PGossipSync::new(Arc::clone(&network_graph), None, Arc::clone(&logger));
8720 let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), Arc::clone(&network_graph), Arc::clone(&logger));
8721 let random_seed_bytes = [42; 32];
8722 let config = UserConfig::default();
8723
8724 let amt_msat = 7_4009_8048;
8726 let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
8727 let first_hops = [get_channel_details(
8728 Some(200), nodes[0], channelmanager::provided_init_features(&config), 2_7345_2000
8729 )];
8730
8731 add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[6], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6);
8732 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
8733 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8734 short_channel_id: 6,
8735 timestamp: 1,
8736 message_flags: 1, channel_flags: 0,
8738 cltv_expiry_delta: (6 << 4) | 0,
8739 htlc_minimum_msat: 0,
8740 htlc_maximum_msat: MAX_VALUE_MSAT,
8741 fee_base_msat: 0,
8742 fee_proportional_millionths: 0,
8743 excess_data: Vec::new()
8744 });
8745 add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[0], NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0);
8746
8747 let htlc_min = 2_5165_8240;
8748 let blinded_hints = vec![
8749 dummy_blinded_path(nodes[0], BlindedPayInfo {
8750 fee_base_msat: 1_6778_3453,
8751 fee_proportional_millionths: 0,
8752 htlc_minimum_msat: htlc_min,
8753 htlc_maximum_msat: htlc_min * 100,
8754 cltv_expiry_delta: 10,
8755 features: BlindedHopFeatures::empty(),
8756 })
8757 ];
8758 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8759 let payment_params = PaymentParameters::blinded(blinded_hints.clone())
8760 .with_bolt12_features(bolt12_features.clone()).unwrap();
8761 let route_params = RouteParameters::from_payment_params_and_value(
8762 payment_params, amt_msat);
8763 let netgraph = network_graph.read_only();
8764
8765 if let Err(err) = get_route(
8766 &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::<Vec<_>>()),
8767 Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(),
8768 &random_seed_bytes
8769 ) {
8770 assert_eq!(err, "Failed to find a path to the given destination");
8771 } else { panic!() }
8772 }
8773
8774 #[test]
8775 #[rustfmt::skip]
8776 fn path_contribution_includes_min_htlc_overpay() {
8777 let secp_ctx = Secp256k1::new();
8782 let logger = Arc::new(ln_test_utils::TestLogger::new());
8783 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8784 let scorer = ProbabilisticScorer::new(ProbabilisticScoringDecayParameters::default(), Arc::clone(&network_graph), Arc::clone(&logger));
8785 let random_seed_bytes = [42; 32];
8786 let config = UserConfig::default();
8787
8788 let amt_msat = 562_0000;
8790 let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
8791 let first_hops = [
8792 get_channel_details(
8793 Some(83), nodes[0], channelmanager::provided_init_features(&config), 2199_0000,
8794 ),
8795 ];
8796
8797 let htlc_mins = [49_0000, 1125_0000];
8798 let payment_params = {
8799 let mut blinded_hints = Vec::new();
8800 for htlc_min in htlc_mins.iter() {
8801 let payinfo = BlindedPayInfo {
8802 fee_base_msat: 0,
8803 fee_proportional_millionths: 0,
8804 htlc_minimum_msat: *htlc_min,
8805 htlc_maximum_msat: *htlc_min * 100,
8806 cltv_expiry_delta: 10,
8807 features: BlindedHopFeatures::empty(),
8808 };
8809 blinded_hints.push(dummy_blinded_path(nodes[0], payinfo));
8810 }
8811 let bolt12_features = channelmanager::provided_bolt12_invoice_features(&config);
8812 PaymentParameters::blinded(blinded_hints.clone())
8813 .with_bolt12_features(bolt12_features.clone()).unwrap()
8814 };
8815
8816 let netgraph = network_graph.read_only();
8817 let route_params = RouteParameters::from_payment_params_and_value(
8818 payment_params, amt_msat);
8819 let route = get_route(
8820 &our_id, &route_params, &netgraph, Some(&first_hops.iter().collect::<Vec<_>>()),
8821 Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(),
8822 &random_seed_bytes
8823 ).unwrap();
8824 assert_eq!(route.paths.len(), 1);
8825 assert_eq!(route.get_total_amount(), amt_msat);
8826 }
8827
8828 #[test]
8829 #[rustfmt::skip]
8830 fn first_hop_preferred_over_hint() {
8831 let secp_ctx = Secp256k1::new();
8834 let logger = Arc::new(ln_test_utils::TestLogger::new());
8835 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
8836 let gossip_sync = P2PGossipSync::new(Arc::clone(&network_graph), None, Arc::clone(&logger));
8837 let scorer = ln_test_utils::TestScorer::new();
8838 let random_seed_bytes = [42; 32];
8839 let config = UserConfig::default();
8840
8841 let amt_msat = 1_000_000;
8842 let (our_privkey, our_node_id, privkeys, nodes) = get_nodes(&secp_ctx);
8843
8844 add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[0],
8845 ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1);
8846 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
8847 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8848 short_channel_id: 1,
8849 timestamp: 1,
8850 message_flags: 1, channel_flags: 0,
8852 cltv_expiry_delta: 42,
8853 htlc_minimum_msat: 1_000,
8854 htlc_maximum_msat: 10_000_000,
8855 fee_base_msat: 800,
8856 fee_proportional_millionths: 0,
8857 excess_data: Vec::new()
8858 });
8859 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
8860 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8861 short_channel_id: 1,
8862 timestamp: 1,
8863 message_flags: 1, channel_flags: 1,
8865 cltv_expiry_delta: 42,
8866 htlc_minimum_msat: 1_000,
8867 htlc_maximum_msat: 10_000_000,
8868 fee_base_msat: 800,
8869 fee_proportional_millionths: 0,
8870 excess_data: Vec::new()
8871 });
8872
8873 add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[1],
8874 ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 2);
8875 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
8876 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8877 short_channel_id: 2,
8878 timestamp: 2,
8879 message_flags: 1, channel_flags: 0,
8881 cltv_expiry_delta: 42,
8882 htlc_minimum_msat: 1_000,
8883 htlc_maximum_msat: 10_000_000,
8884 fee_base_msat: 800,
8885 fee_proportional_millionths: 0,
8886 excess_data: Vec::new()
8887 });
8888 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
8889 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8890 short_channel_id: 2,
8891 timestamp: 2,
8892 message_flags: 1, channel_flags: 1,
8894 cltv_expiry_delta: 42,
8895 htlc_minimum_msat: 1_000,
8896 htlc_maximum_msat: 10_000_000,
8897 fee_base_msat: 800,
8898 fee_proportional_millionths: 0,
8899 excess_data: Vec::new()
8900 });
8901
8902 let dest_node_id = nodes[2];
8903
8904 let route_hint = RouteHint(vec![RouteHintHop {
8905 src_node_id: our_node_id,
8906 short_channel_id: 44,
8907 fees: RoutingFees {
8908 base_msat: 234,
8909 proportional_millionths: 0,
8910 },
8911 cltv_expiry_delta: 10,
8912 htlc_minimum_msat: None,
8913 htlc_maximum_msat: Some(5_000_000),
8914 },
8915 RouteHintHop {
8916 src_node_id: nodes[0],
8917 short_channel_id: 45,
8918 fees: RoutingFees {
8919 base_msat: 123,
8920 proportional_millionths: 0,
8921 },
8922 cltv_expiry_delta: 10,
8923 htlc_minimum_msat: None,
8924 htlc_maximum_msat: None,
8925 }]);
8926
8927 let payment_params = PaymentParameters::from_node_id(dest_node_id, 42)
8928 .with_route_hints(vec![route_hint]).unwrap()
8929 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap();
8930 let route_params = RouteParameters::from_payment_params_and_value(
8931 payment_params, amt_msat);
8932
8933 let first_hops = [get_channel_details(Some(1), nodes[0],
8936 channelmanager::provided_init_features(&config), 999_999)];
8937
8938 let route = get_route(&our_node_id, &route_params.clone(), &network_graph.read_only(),
8939 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
8940 &Default::default(), &random_seed_bytes).unwrap();
8941 assert_eq!(route.paths.len(), 1);
8942 assert_eq!(route.get_total_amount(), amt_msat);
8943 assert_eq!(route.paths[0].hops.len(), 2);
8944 assert_eq!(route.paths[0].hops[0].short_channel_id, 44);
8945 assert_eq!(route.paths[0].hops[1].short_channel_id, 45);
8946 assert_eq!(route.get_total_fees(), 123);
8947
8948 let mut first_hop = get_channel_details(Some(1), nodes[0], channelmanager::provided_init_features(&config), 999_999);
8951 first_hop.outbound_scid_alias = Some(44);
8952 let first_hops = [first_hop];
8953
8954 let route_res = get_route(&our_node_id, &route_params.clone(), &network_graph.read_only(),
8955 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
8956 &Default::default(), &random_seed_bytes);
8957 assert!(route_res.is_err());
8958
8959 let mut first_hop = get_channel_details(Some(1), nodes[0],
8962 channelmanager::provided_init_features(&config), 10_000_000);
8963 first_hop.outbound_scid_alias = Some(44);
8964 let first_hops = [first_hop];
8965
8966 let route = get_route(&our_node_id, &route_params.clone(), &network_graph.read_only(),
8967 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
8968 &Default::default(), &random_seed_bytes).unwrap();
8969 assert_eq!(route.paths.len(), 1);
8970 assert_eq!(route.get_total_amount(), amt_msat);
8971 assert_eq!(route.paths[0].hops.len(), 2);
8972 assert_eq!(route.paths[0].hops[0].short_channel_id, 1);
8973 assert_eq!(route.paths[0].hops[1].short_channel_id, 45);
8974 assert_eq!(route.get_total_fees(), 123);
8975 }
8976
8977 #[test]
8978 #[rustfmt::skip]
8979 fn test_max_final_contribution() {
8980 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
8986 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
8987 let scorer = ln_test_utils::TestScorer::new();
8988 let random_seed_bytes = [42; 32];
8989
8990 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
8992 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
8993 short_channel_id: 1,
8994 timestamp: 2,
8995 message_flags: 1, channel_flags: 0,
8997 cltv_expiry_delta: (1 << 4) | 1,
8998 htlc_minimum_msat: 0,
8999 htlc_maximum_msat: 1_000_000,
9000 fee_base_msat: 0,
9001 fee_proportional_millionths: 0,
9002 excess_data: Vec::new()
9003 });
9004
9005 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
9007 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9008 short_channel_id: 3,
9009 timestamp: 2,
9010 message_flags: 1, channel_flags: 0,
9012 cltv_expiry_delta: (3 << 4) | 1,
9013 htlc_minimum_msat: 0,
9014 htlc_maximum_msat: 1_000_000_000,
9015 fee_base_msat: 0,
9016 fee_proportional_millionths: 0,
9017 excess_data: Vec::new()
9018 });
9019
9020 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
9022 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9023 short_channel_id: 6,
9024 timestamp: 2,
9025 message_flags: 1, channel_flags: 0,
9027 cltv_expiry_delta: (6 << 4) | 1,
9028 htlc_minimum_msat: 0,
9029 htlc_maximum_msat: 1_000_000_000,
9030 fee_base_msat: 0,
9031 fee_proportional_millionths: 1,
9032 excess_data: Vec::new()
9033 });
9034
9035 let config = UserConfig::default();
9039 let payment_params = PaymentParameters::from_node_id(nodes[4], 42)
9040 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
9041 .unwrap();
9042 let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1_000_000);
9043 get_route(&our_id, &route_params, &network_graph.read_only(), None,
9044 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap_err();
9045
9046 update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
9048 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9049 short_channel_id: 1,
9050 timestamp: 3,
9051 message_flags: 1, channel_flags: 0,
9053 cltv_expiry_delta: (1 << 4) | 1,
9054 htlc_minimum_msat: 0,
9055 htlc_maximum_msat: 1_000_001,
9056 fee_base_msat: 0,
9057 fee_proportional_millionths: 0,
9058 excess_data: Vec::new()
9059 });
9060
9061 let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
9063 Arc::clone(&logger), &scorer, &Default::default(), &random_seed_bytes).unwrap();
9064 assert_eq!(route.paths.len(), 1);
9065 assert_eq!(route.paths[0].hops.len(), 3);
9066 assert_eq!(route.paths[0].hops[0].short_channel_id, 1);
9067 assert_eq!(route.paths[0].hops[1].short_channel_id, 3);
9068 assert_eq!(route.paths[0].hops[2].short_channel_id, 6);
9069 }
9070
9071 #[test]
9072 #[rustfmt::skip]
9073 fn allow_us_being_first_hint() {
9074 let secp_ctx = Secp256k1::new();
9076 let logger = Arc::new(ln_test_utils::TestLogger::new());
9077 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
9078 let scorer = ln_test_utils::TestScorer::new();
9079 let random_seed_bytes = [42; 32];
9080 let config = UserConfig::default();
9081
9082 let (_, our_node_id, _, nodes) = get_nodes(&secp_ctx);
9083
9084 let amt_msat = 1_000_000;
9085 let dest_node_id = nodes[1];
9086
9087 let first_hops = [
9088 get_channel_details(Some(1), nodes[0], channelmanager::provided_init_features(&config), 10_000_000),
9089 ];
9090
9091 let route_hint = RouteHint(vec![RouteHintHop {
9092 src_node_id: our_node_id,
9093 short_channel_id: 44,
9094 fees: RoutingFees {
9095 base_msat: 123,
9096 proportional_millionths: 0,
9097 },
9098 cltv_expiry_delta: 10,
9099 htlc_minimum_msat: None,
9100 htlc_maximum_msat: None,
9101 }]);
9102
9103 let payment_params = PaymentParameters::from_node_id(dest_node_id, 42)
9104 .with_route_hints(vec![route_hint]).unwrap()
9105 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config)).unwrap();
9106
9107 let route_params = RouteParameters::from_payment_params_and_value(
9108 payment_params, amt_msat);
9109
9110
9111 let route = get_route(&our_node_id, &route_params, &network_graph.read_only(),
9112 Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
9113 &Default::default(), &random_seed_bytes).unwrap();
9114
9115 assert_eq!(route.paths.len(), 1);
9116 assert_eq!(route.get_total_amount(), amt_msat);
9117 assert_eq!(route.get_total_fees(), 0);
9118 assert_eq!(route.paths[0].hops.len(), 1);
9119
9120 assert_eq!(route.paths[0].hops[0].short_channel_id, 44);
9121 }
9122
9123 #[test]
9124 fn aggregated_prop_fee_overflow_fails_route() {
9125 let secp_ctx = Secp256k1::new();
9129 let logger = Arc::new(ln_test_utils::TestLogger::new());
9130 let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, Arc::clone(&logger)));
9131 let scorer = ln_test_utils::TestScorer::new();
9132 let random_seed_bytes = [42; 32];
9133 let config = UserConfig::default();
9134
9135 let (_, our_node_id, _, nodes) = get_nodes(&secp_ctx);
9136 let route_hint = RouteHint(vec![
9137 RouteHintHop {
9138 src_node_id: nodes[0],
9139 short_channel_id: 100,
9140 fees: RoutingFees { base_msat: 0, proportional_millionths: u32::MAX },
9141 cltv_expiry_delta: 10,
9142 htlc_minimum_msat: None,
9143 htlc_maximum_msat: None,
9144 },
9145 RouteHintHop {
9146 src_node_id: nodes[1],
9147 short_channel_id: 101,
9148 fees: RoutingFees { base_msat: 0, proportional_millionths: u32::MAX },
9149 cltv_expiry_delta: 10,
9150 htlc_minimum_msat: None,
9151 htlc_maximum_msat: None,
9152 },
9153 ]);
9154
9155 let payment_params = PaymentParameters::from_node_id(nodes[2], 42)
9156 .with_route_hints(vec![route_hint])
9157 .unwrap()
9158 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
9159 .unwrap();
9160 let first_hops = [get_channel_details(
9161 Some(1),
9162 nodes[0],
9163 channelmanager::provided_init_features(&config),
9164 100_000_000,
9165 )];
9166 let route_params = RouteParameters {
9167 payment_params,
9168 final_value_msat: 1,
9169 max_total_routing_fee_msat: None,
9170 };
9171 let route = get_route(
9172 &our_node_id,
9173 &route_params,
9174 &network_graph.read_only(),
9175 Some(&first_hops.iter().collect::<Vec<_>>()),
9176 Arc::clone(&logger),
9177 &scorer,
9178 &Default::default(),
9179 &random_seed_bytes,
9180 );
9181 assert!(route.is_err());
9182 }
9183
9184 #[test]
9185 fn prefers_paths_by_cost_amt_ratio() {
9186 let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
9195 let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
9196 let scorer = ln_test_utils::TestScorer::new();
9197 let random_seed_bytes = [42; 32];
9198
9199 let update_1 = UnsignedChannelUpdate {
9201 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9202 short_channel_id: 1,
9203 timestamp: 2,
9204 message_flags: 1, channel_flags: 0,
9206 cltv_expiry_delta: (1 << 4) | 1,
9207 htlc_minimum_msat: 0,
9208 htlc_maximum_msat: 10_000_000,
9209 fee_base_msat: 0,
9210 fee_proportional_millionths: 0,
9211 excess_data: Vec::new(),
9212 };
9213 update_channel(&gossip_sync, &secp_ctx, &our_privkey, update_1);
9214
9215 let update_3 = UnsignedChannelUpdate {
9217 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9218 short_channel_id: 3,
9219 timestamp: 2,
9220 message_flags: 1, channel_flags: 0,
9222 cltv_expiry_delta: (3 << 4) | 1,
9223 htlc_minimum_msat: 0,
9224 htlc_maximum_msat: 1_000_000,
9225 fee_base_msat: 1_000,
9226 fee_proportional_millionths: 0,
9227 excess_data: Vec::new(),
9228 };
9229 update_channel(&gossip_sync, &secp_ctx, &privkeys[0], update_3);
9230
9231 let update_13 = UnsignedChannelUpdate {
9233 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9234 short_channel_id: 13,
9235 timestamp: 2,
9236 message_flags: 1, channel_flags: 0,
9238 cltv_expiry_delta: (13 << 4) | 1,
9239 htlc_minimum_msat: 0,
9240 htlc_maximum_msat: 1_000_000,
9241 fee_base_msat: 1_000,
9242 fee_proportional_millionths: 0,
9243 excess_data: Vec::new(),
9244 };
9245 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], update_13);
9246
9247 let update_4 = UnsignedChannelUpdate {
9249 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9250 short_channel_id: 4,
9251 timestamp: 2,
9252 message_flags: 1, channel_flags: 0,
9254 cltv_expiry_delta: (4 << 4) | 1,
9255 htlc_minimum_msat: 0,
9256 htlc_maximum_msat: 1_000_000,
9257 fee_base_msat: 1_000,
9258 fee_proportional_millionths: 0,
9259 excess_data: Vec::new(),
9260 };
9261 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], update_4);
9262
9263 for i in 0..6 {
9269 let chan_features = ChannelFeatures::from_le_bytes(vec![]);
9272 add_channel(&gossip_sync, &secp_ctx, &privkeys[7], &privkeys[2], chan_features, i + 42);
9273
9274 let update_a = UnsignedChannelUpdate {
9276 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9277 short_channel_id: i + 42,
9278 timestamp: 2,
9279 message_flags: 1, channel_flags: 0,
9281 cltv_expiry_delta: (42 << 4) | 1,
9282 htlc_minimum_msat: 0,
9283 htlc_maximum_msat: 1_000_000,
9284 fee_base_msat: 1_000,
9285 fee_proportional_millionths: 0,
9286 excess_data: Vec::new(),
9287 };
9288 update_channel(&gossip_sync, &secp_ctx, &privkeys[7], update_a);
9289
9290 let update_b = UnsignedChannelUpdate {
9292 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9293 short_channel_id: i + 42,
9294 timestamp: 2,
9295 message_flags: 1, channel_flags: 1,
9297 cltv_expiry_delta: (42 << 4) | 1,
9298 htlc_minimum_msat: 0,
9299 htlc_maximum_msat: 10_000_000,
9300 fee_base_msat: u32::MAX,
9301 fee_proportional_millionths: 0,
9302 excess_data: Vec::new(),
9303 };
9304 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], update_b);
9305 }
9306
9307 let config = UserConfig::default();
9309 let mut payment_params = PaymentParameters::from_node_id(nodes[2], 42)
9310 .with_bolt11_features(channelmanager::provided_bolt11_invoice_features(&config))
9311 .unwrap();
9312 payment_params.max_channel_saturation_power_of_half = 0;
9313 let route_params =
9314 RouteParameters::from_payment_params_and_value(payment_params, 3_000_000);
9315 let route = get_route(
9316 &our_id,
9317 &route_params,
9318 &network_graph.read_only(),
9319 None,
9320 Arc::clone(&logger),
9321 &scorer,
9322 &Default::default(),
9323 &random_seed_bytes,
9324 )
9325 .unwrap();
9326 assert_eq!(route.paths.len(), 3);
9327 for path in route.paths {
9328 assert_eq!(path.hops.len(), 2);
9329 }
9330
9331 let features_16 = ChannelFeatures::from_le_bytes(id_to_feature_flags(16));
9334 add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[2], features_16, 16);
9335
9336 let update_16_a = UnsignedChannelUpdate {
9338 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9339 short_channel_id: 16,
9340 timestamp: 2,
9341 message_flags: 1, channel_flags: 0,
9343 cltv_expiry_delta: (16 << 4) | 1,
9344 htlc_minimum_msat: 0,
9345 htlc_maximum_msat: 3_000_000,
9346 fee_base_msat: 2_000,
9347 fee_proportional_millionths: 0,
9348 excess_data: Vec::new(),
9349 };
9350 update_channel(&gossip_sync, &secp_ctx, &privkeys[1], update_16_a);
9351
9352 let update_16_b = UnsignedChannelUpdate {
9354 chain_hash: ChainHash::using_genesis_block(Network::Testnet),
9355 short_channel_id: 16,
9356 timestamp: 2,
9357 message_flags: 1, channel_flags: 1,
9359 cltv_expiry_delta: (16 << 4) | 1,
9360 htlc_minimum_msat: 0,
9361 htlc_maximum_msat: 10_000_000,
9362 fee_base_msat: u32::MAX,
9363 fee_proportional_millionths: 0,
9364 excess_data: Vec::new(),
9365 };
9366 update_channel(&gossip_sync, &secp_ctx, &privkeys[2], update_16_b);
9367
9368 let route = get_route(
9370 &our_id,
9371 &route_params,
9372 &network_graph.read_only(),
9373 None,
9374 Arc::clone(&logger),
9375 &scorer,
9376 &Default::default(),
9377 &random_seed_bytes,
9378 )
9379 .unwrap();
9380 assert_eq!(route.paths.len(), 1);
9381 assert_eq!(route.paths[0].hops.len(), 2);
9382 assert_eq!(route.paths[0].hops[1].short_channel_id, 16);
9383 }
9384}
9385
9386#[cfg(any(test, ldk_bench))]
9387pub(crate) mod bench_utils {
9388 use super::*;
9389 use bitcoin::hashes::Hash;
9390 use bitcoin::secp256k1::SecretKey;
9391 use std::fs::File;
9392 use std::io::Read;
9393
9394 use crate::chain::transaction::OutPoint;
9395 use crate::ln::chan_utils::make_funding_redeemscript;
9396 use crate::ln::channel_state::{ChannelCounterparty, ChannelShutdownState};
9397 use crate::ln::channelmanager;
9398 use crate::ln::types::ChannelId;
9399 use crate::routing::scoring::{ProbabilisticScorer, ScoreUpdate};
9400 use crate::sync::Arc;
9401 use crate::util::config::UserConfig;
9402 use crate::util::test_utils::TestLogger;
9403
9404 #[rustfmt::skip]
9406 pub(crate) fn get_graph_scorer_file() -> Result<(std::fs::File, std::fs::File), &'static str> {
9407 let load_file = |fname, err_str| {
9408 File::open(fname) .or_else(|_| File::open(&format!("lightning/{}", fname))) .or_else(|_| { let mut path = std::env::current_exe().unwrap();
9413 path.pop(); path.pop(); path.pop(); path.pop(); path.push("lightning");
9418 path.push(fname);
9419 File::open(path)
9420 })
9421 .or_else(|_| { let mut path = std::env::current_exe().unwrap();
9424 path.pop(); path.pop(); path.pop(); path.pop(); path.pop(); path.push("lightning");
9430 path.push(fname);
9431 File::open(path)
9432 })
9433 .map_err(|_| err_str)
9434 };
9435 let graph_res = load_file(
9436 "net_graph-2023-12-10.bin",
9437 "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"
9438 );
9439 let scorer_res = load_file(
9440 "scorer-2023-12-10.bin",
9441 "Please fetch https://bitcoin.ninja/ldk-scorer-v0.0.118-2023-12-10.bin and place it at lightning/scorer-2023-12-10.bin"
9442 );
9443 #[cfg(require_route_graph_test)]
9444 return Ok((graph_res.unwrap(), scorer_res.unwrap()));
9445 #[cfg(not(require_route_graph_test))]
9446 return Ok((graph_res?, scorer_res?));
9447 }
9448
9449 pub(crate) fn read_graph_scorer(
9450 logger: &TestLogger,
9451 ) -> Result<
9452 (
9453 Arc<NetworkGraph<&TestLogger>>,
9454 ProbabilisticScorer<Arc<NetworkGraph<&TestLogger>>, &TestLogger>,
9455 ),
9456 &'static str,
9457 > {
9458 let (mut graph_file, mut scorer_file) = get_graph_scorer_file()?;
9459 let mut graph_buffer = Vec::new();
9460 let mut scorer_buffer = Vec::new();
9461 graph_file.read_to_end(&mut graph_buffer).unwrap();
9462 scorer_file.read_to_end(&mut scorer_buffer).unwrap();
9463 let graph = Arc::new(NetworkGraph::read(&mut &graph_buffer[..], logger).unwrap());
9464 let scorer_args = (Default::default(), Arc::clone(&graph), logger);
9465 let scorer = ProbabilisticScorer::read(&mut &scorer_buffer[..], scorer_args).unwrap();
9466 Ok((graph, scorer))
9467 }
9468
9469 pub(crate) fn payer_pubkey() -> PublicKey {
9470 let secp_ctx = Secp256k1::new();
9471 PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap())
9472 }
9473
9474 #[inline]
9475 #[rustfmt::skip]
9476 pub(crate) fn first_hop(node_id: PublicKey) -> ChannelDetails {
9477 #[allow(deprecated)] ChannelDetails {
9479 channel_id: ChannelId::new_zero(),
9480 counterparty: ChannelCounterparty {
9481 features: channelmanager::provided_init_features(&UserConfig::default()),
9482 node_id,
9483 unspendable_punishment_reserve: 0,
9484 forwarding_info: None,
9485 outbound_htlc_minimum_msat: None,
9486 outbound_htlc_maximum_msat: None,
9487 },
9488 funding_txo: Some(OutPoint {
9489 txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0
9490 }),
9491 funding_redeem_script: Some(make_funding_redeemscript(
9492 &PublicKey::from_slice(&[2; 33]).unwrap(),
9493 &PublicKey::from_slice(&[2; 33]).unwrap(),
9494 )),
9495 channel_type: None,
9496 short_channel_id: Some(1),
9497 inbound_scid_alias: None,
9498 outbound_scid_alias: None,
9499 channel_value_satoshis: 10_000_000_000,
9500 user_channel_id: 0,
9501 outbound_capacity_msat: 10_000_000_000,
9502 next_outbound_htlc_minimum_msat: 0,
9503 next_outbound_htlc_limit_msat: 10_000_000_000,
9504 inbound_capacity_msat: 0,
9505 unspendable_punishment_reserve: None,
9506 confirmations_required: None,
9507 confirmations: None,
9508 force_close_spend_delay: None,
9509 is_outbound: true,
9510 is_channel_ready: true,
9511 is_usable: true,
9512 is_announced: true,
9513 inbound_htlc_minimum_msat: None,
9514 inbound_htlc_maximum_msat: None,
9515 config: None,
9516 feerate_sat_per_1000_weight: None,
9517 channel_shutdown_state: Some(ChannelShutdownState::NotShuttingDown),
9518 pending_inbound_htlcs: Vec::new(),
9519 pending_outbound_htlcs: Vec::new(),
9520 }
9521 }
9522
9523 #[rustfmt::skip]
9524 pub(crate) fn generate_test_routes<S: ScoreLookUp + ScoreUpdate>(graph: &NetworkGraph<&TestLogger>, scorer: &mut S,
9525 score_params: &S::ScoreParams, features: Bolt11InvoiceFeatures, mut seed: u64,
9526 starting_amount: u64, route_count: usize,
9527 ) -> Vec<(ChannelDetails, PaymentParameters, u64)> {
9528 let payer = payer_pubkey();
9529 let random_seed_bytes = [42; 32];
9530
9531 let mut nodes = graph.read_only().nodes().clone();
9532 let mut route_endpoints = Vec::new();
9533 for _ in 0..route_count {
9534 loop {
9535 seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0;
9536 let src_idx = (seed as usize) % nodes.len();
9537 let src_key = nodes.range(..).skip(src_idx).next().unwrap().0;
9538 let src = PublicKey::from_slice(src_key.as_slice()).unwrap();
9539
9540 seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0;
9541 let dst_idx = (seed as usize) % nodes.len();
9542 let dst_key = nodes.range(..).skip(dst_idx).next().unwrap().0;
9543 let dst = PublicKey::from_slice(dst_key.as_slice()).unwrap();
9544
9545 let params = PaymentParameters::from_node_id(dst, 42)
9546 .with_bolt11_features(features.clone()).unwrap();
9547 let first_hop = first_hop(src);
9548 let amt_msat = starting_amount + seed % 1_000_000;
9549 let route_params = RouteParameters::from_payment_params_and_value(
9550 params.clone(), amt_msat);
9551 let path_exists =
9552 get_route(&payer, &route_params, &graph.read_only(), Some(&[&first_hop]),
9553 &TestLogger::new(), scorer, score_params, &random_seed_bytes).is_ok();
9554 if path_exists {
9555 route_endpoints.push((first_hop, params, amt_msat));
9556 break;
9557 }
9558 }
9559 }
9560
9561 route_endpoints
9562 }
9563}
9564
9565#[cfg(ldk_bench)]
9566pub mod benches {
9567 use super::*;
9568 use crate::ln::channelmanager;
9569 use crate::routing::gossip::NetworkGraph;
9570 use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScoringFeeParameters};
9571 use crate::routing::scoring::{ScoreLookUp, ScoreUpdate};
9572 use crate::types::features::Bolt11InvoiceFeatures;
9573 use crate::util::config::UserConfig;
9574 use crate::util::logger::{Logger, Record};
9575 use crate::util::test_utils::TestLogger;
9576
9577 use criterion::Criterion;
9578
9579 struct DummyLogger {}
9580 impl Logger for DummyLogger {
9581 fn log(&self, _record: Record) {}
9582 }
9583
9584 #[rustfmt::skip]
9585 pub fn generate_routes_with_zero_penalty_scorer(bench: &mut Criterion) {
9586 let logger = TestLogger::new();
9587 let (network_graph, _) = bench_utils::read_graph_scorer(&logger).unwrap();
9588 let scorer = FixedPenaltyScorer::with_penalty(0);
9589 generate_routes(bench, &network_graph, scorer, &Default::default(),
9590 Bolt11InvoiceFeatures::empty(), 0, "generate_routes_with_zero_penalty_scorer");
9591 }
9592
9593 #[rustfmt::skip]
9594 pub fn generate_mpp_routes_with_zero_penalty_scorer(bench: &mut Criterion) {
9595 let logger = TestLogger::new();
9596 let (network_graph, _) = bench_utils::read_graph_scorer(&logger).unwrap();
9597 let scorer = FixedPenaltyScorer::with_penalty(0);
9598 generate_routes(bench, &network_graph, scorer, &Default::default(),
9599 channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0,
9600 "generate_mpp_routes_with_zero_penalty_scorer");
9601 }
9602
9603 #[rustfmt::skip]
9604 pub fn generate_routes_with_probabilistic_scorer(bench: &mut Criterion) {
9605 let logger = TestLogger::new();
9606 let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap();
9607 let params = ProbabilisticScoringFeeParameters::default();
9608 generate_routes(bench, &network_graph, scorer, ¶ms, Bolt11InvoiceFeatures::empty(), 0,
9609 "generate_routes_with_probabilistic_scorer");
9610 }
9611
9612 #[rustfmt::skip]
9613 pub fn generate_mpp_routes_with_probabilistic_scorer(bench: &mut Criterion) {
9614 let logger = TestLogger::new();
9615 let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap();
9616 let params = ProbabilisticScoringFeeParameters::default();
9617 generate_routes(bench, &network_graph, scorer, ¶ms,
9618 channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0,
9619 "generate_mpp_routes_with_probabilistic_scorer");
9620 }
9621
9622 #[rustfmt::skip]
9623 pub fn generate_large_mpp_routes_with_probabilistic_scorer(bench: &mut Criterion) {
9624 let logger = TestLogger::new();
9625 let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap();
9626 let params = ProbabilisticScoringFeeParameters::default();
9627 generate_routes(bench, &network_graph, scorer, ¶ms,
9628 channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 100_000_000,
9629 "generate_large_mpp_routes_with_probabilistic_scorer");
9630 }
9631
9632 #[rustfmt::skip]
9633 pub fn generate_routes_with_nonlinear_probabilistic_scorer(bench: &mut Criterion) {
9634 let logger = TestLogger::new();
9635 let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap();
9636 let mut params = ProbabilisticScoringFeeParameters::default();
9637 params.linear_success_probability = false;
9638 generate_routes(bench, &network_graph, scorer, ¶ms,
9639 channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0,
9640 "generate_routes_with_nonlinear_probabilistic_scorer");
9641 }
9642
9643 #[rustfmt::skip]
9644 pub fn generate_mpp_routes_with_nonlinear_probabilistic_scorer(bench: &mut Criterion) {
9645 let logger = TestLogger::new();
9646 let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap();
9647 let mut params = ProbabilisticScoringFeeParameters::default();
9648 params.linear_success_probability = false;
9649 generate_routes(bench, &network_graph, scorer, ¶ms,
9650 channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 0,
9651 "generate_mpp_routes_with_nonlinear_probabilistic_scorer");
9652 }
9653
9654 #[rustfmt::skip]
9655 pub fn generate_large_mpp_routes_with_nonlinear_probabilistic_scorer(bench: &mut Criterion) {
9656 let logger = TestLogger::new();
9657 let (network_graph, scorer) = bench_utils::read_graph_scorer(&logger).unwrap();
9658 let mut params = ProbabilisticScoringFeeParameters::default();
9659 params.linear_success_probability = false;
9660 generate_routes(bench, &network_graph, scorer, ¶ms,
9661 channelmanager::provided_bolt11_invoice_features(&UserConfig::default()), 100_000_000,
9662 "generate_large_mpp_routes_with_nonlinear_probabilistic_scorer");
9663 }
9664
9665 #[rustfmt::skip]
9666 fn generate_routes<S: ScoreLookUp + ScoreUpdate>(
9667 bench: &mut Criterion, graph: &NetworkGraph<&TestLogger>, mut scorer: S,
9668 score_params: &S::ScoreParams, features: Bolt11InvoiceFeatures, starting_amount: u64,
9669 bench_name: &'static str,
9670 ) {
9671 let route_endpoints = bench_utils::generate_test_routes(graph, &mut scorer, score_params, features, 0xdeadbeef, starting_amount, 50);
9673
9674 do_route_bench(bench, graph, scorer, score_params, bench_name, route_endpoints);
9676 }
9677
9678 #[inline(never)]
9679 #[rustfmt::skip]
9680 fn do_route_bench<S: ScoreLookUp + ScoreUpdate>(
9681 bench: &mut Criterion, graph: &NetworkGraph<&TestLogger>, scorer: S,
9682 score_params: &S::ScoreParams, bench_name: &'static str,
9683 route_endpoints: Vec<(ChannelDetails, PaymentParameters, u64)>,
9684 ) {
9685 let payer = bench_utils::payer_pubkey();
9686 let random_seed_bytes = [42; 32];
9687
9688 let mut idx = 0;
9689 bench.bench_function(bench_name, |b| b.iter(|| {
9690 let (first_hop, params, amt) = &route_endpoints[idx % route_endpoints.len()];
9691 let route_params = RouteParameters::from_payment_params_and_value(params.clone(), *amt);
9692 assert!(get_route(&payer, &route_params, &graph.read_only(), Some(&[first_hop]),
9693 &DummyLogger{}, &scorer, score_params, &random_seed_bytes).is_ok());
9694 idx += 1;
9695 }));
9696 }
9697}