Introduce payment dummy hops in DefaultRouter
What changed, and why it matters
This commit changes how LDK builds private payment routes for BOLT12 offers. Instead of revealing the real number of hops to the payee, it now pads every blinded payment path with three fake 'dummy hops' by default. This is a privacy improvement, not a security bug fix. The code itself does not appear to fix a vulnerability; it adds a feature that makes payment paths look longer and more uniform, which can help hide the recipient's network position. The change also updates many tests to expect these extra dummy hops.
No immediate security action required. Treat as a normal privacy enhancement. Review whether the intentional overpayment when the payer is the introduction node is acceptable for your use case, and verify that downstream BOLT12 payment tests and fee expectations are updated accordingly.
Security signals we found
Adds default dummy hops to all DefaultRouter-generated BlindedPaymentPaths
Switches from BlindedPaymentPath::new to BlindedPaymentPath::new_with_dummy_hops
Updates tests to expect extra forwarding hops and adjusted failure behavior
Comment acknowledges intentional fee overpayment when payer is introduction node
Evidence from the diff
The commit introduces DEFAULT_PAYMENT_DUMMY_HOPS = 3 in DefaultRouter and switches BlindedPaymentPath construction from new() to new_with_dummy_hops(), injecting three default DummyTlvs entries into every generated blinded payment path. Test code is updated to add dummy hops when manually passing payments along paths and to process extra pending HTLC forwarding steps. A comment in offers_tests.rs notes a small, intentional overpayment when the payer is the introduction node, because LDK does not subtract the forward fee for the payer->next_hop channel. The change is a privacy enhancement for BOLT12 blinded paths, not a patch for an exploitable weakness.
Changed components
lightning/src/routing/router.rslightning/src/ln/offers_tests.rslightning/src/ln/async_payments_tests.rslightning-dns-resolver/src/lib.rsInspect captured patch +89 / −37
diff --git a/lightning-dns-resolver/src/lib.rs b/lightning-dns-resolver/src/lib.rs
index 125d431..b7f429d 100644
--- a/lightning-dns-resolver/src/lib.rs
+++ b/lightning-dns-resolver/src/lib.rs
@@ -175,6 +175,7 @@ mod test {
use lightning::onion_message::messenger::{
AOnionMessenger, Destination, MessageRouter, OnionMessagePath, OnionMessenger,
};
+ use lightning::routing::router::DEFAULT_PAYMENT_DUMMY_HOPS;
use lightning::sign::{KeysManager, NodeSigner, ReceiveAuthKey, Recipient};
use lightning::types::features::InitFeatures;
use lightning::types::payment::PaymentHash;
@@ -419,6 +420,12 @@ mod test {
let updates = get_htlc_update_msgs(&nodes[0], &payee_id);
nodes[1].node.handle_update_add_htlc(payer_id, &updates.update_add_htlcs[0]);
do_commitment_signed_dance(&nodes[1], &nodes[0], &updates.commitment_signed, false, false);
+
+ for _ in 0..DEFAULT_PAYMENT_DUMMY_HOPS {
+ assert!(nodes[1].node.needs_pending_htlc_processing());
+ nodes[1].node.process_pending_htlc_forwards();
+ }
+
expect_and_process_pending_htlcs(&nodes[1], false);
let claimable_events = nodes[1].node.get_and_clear_pending_events();
diff --git a/lightning/src/ln/async_payments_tests.rs b/lightning/src/ln/async_payments_tests.rs
index 8e7fbdf..a485e77 100644
--- a/lightning/src/ln/async_payments_tests.rs
+++ b/lightning/src/ln/async_payments_tests.rs
@@ -10,8 +10,8 @@
use crate::blinded_path::message::{
BlindedMessagePath, MessageContext, NextMessageHop, OffersContext,
};
-use crate::blinded_path::payment::PaymentContext;
use crate::blinded_path::payment::{AsyncBolt12OfferContext, BlindedPaymentTlvs};
+use crate::blinded_path::payment::{DummyTlvs, PaymentContext};
use crate::chain::channelmonitor::{HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
use crate::events::{
Event, EventsProvider, HTLCHandlingFailureReason, HTLCHandlingFailureType, PaidBolt12Invoice,
@@ -55,7 +55,7 @@ use crate::onion_message::messenger::{
use crate::onion_message::offers::OffersMessage;
use crate::onion_message::packet::ParsedOnionMessageContents;
use crate::prelude::*;
-use crate::routing::router::{Payee, PaymentParameters};
+use crate::routing::router::{Payee, PaymentParameters, DEFAULT_PAYMENT_DUMMY_HOPS};
use crate::sign::NodeSigner;
use crate::sync::Mutex;
use crate::types::features::Bolt12InvoiceFeatures;
@@ -984,7 +984,8 @@ fn ignore_duplicate_invoice() {
check_added_monitors!(sender, 1);
let route: &[&[&Node]] = &[&[always_online_node, async_recipient]];
- let args = PassAlongPathArgs::new(sender, route[0], amt_msat, payment_hash, ev);
+ let args = PassAlongPathArgs::new(sender, route[0], amt_msat, payment_hash, ev)
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
let claimable_ev = do_pass_along_path(args).unwrap();
let keysend_preimage = extract_payment_preimage(&claimable_ev);
let (res, _) =
@@ -1063,7 +1064,8 @@ fn ignore_duplicate_invoice() {
check_added_monitors!(sender, 1);
let args = PassAlongPathArgs::new(sender, route[0], amt_msat, payment_hash, ev)
- .without_clearing_recipient_events();
+ .without_clearing_recipient_events()
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
do_pass_along_path(args);
let payment_preimage = match get_event!(async_recipient, Event::PaymentClaimable) {
@@ -1138,7 +1140,8 @@ fn async_receive_flow_success() {
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
let route: &[&[&Node]] = &[&[&nodes[1], &nodes[2]]];
- let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev);
+ let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
let claimable_ev = do_pass_along_path(args).unwrap();
let keysend_preimage = extract_payment_preimage(&claimable_ev);
let (res, _) =
@@ -1375,11 +1378,13 @@ fn async_receive_mpp() {
};
let args = PassAlongPathArgs::new(&nodes[0], expected_route[0], amt_msat, payment_hash, ev)
- .without_claimable_event();
+ .without_claimable_event()
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
do_pass_along_path(args);
let ev = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events);
- let args = PassAlongPathArgs::new(&nodes[0], expected_route[1], amt_msat, payment_hash, ev);
+ let args = PassAlongPathArgs::new(&nodes[0], expected_route[1], amt_msat, payment_hash, ev)
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
let claimable_ev = do_pass_along_path(args).unwrap();
let keysend_preimage = match claimable_ev {
Event::PaymentClaimable {
@@ -1497,7 +1502,8 @@ fn amount_doesnt_match_invreq() {
let route: &[&[&Node]] = &[&[&nodes[1], &nodes[3]]];
let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
.without_claimable_event()
- .expect_failure(HTLCHandlingFailureType::Receive { payment_hash });
+ .expect_failure(HTLCHandlingFailureType::Receive { payment_hash })
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
do_pass_along_path(args);
// Modify the invoice request stored in our outbounds to be the correct one, to make sure the
@@ -1521,7 +1527,8 @@ fn amount_doesnt_match_invreq() {
ev, MessageSendEvent::UpdateHTLCs { ref updates, .. } if updates.update_add_htlcs.len() == 1));
check_added_monitors!(nodes[0], 1);
let route: &[&[&Node]] = &[&[&nodes[2], &nodes[3]]];
- let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev);
+ let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
let claimable_ev = do_pass_along_path(args).unwrap();
let keysend_preimage = extract_payment_preimage(&claimable_ev);
claim_payment_along_route(ClaimAlongRouteArgs::new(&nodes[0], route, keysend_preimage));
@@ -1712,7 +1719,8 @@ fn invalid_async_receive_with_retry<F1, F2>(
let payment_hash = extract_payment_hash(&ev);
let route: &[&[&Node]] = &[&[&nodes[1], &nodes[2]]];
- let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev);
+ let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
do_pass_along_path(args);
// Fail the HTLC backwards to enable us to more easily modify the now-Retryable outbound to test
@@ -1739,7 +1747,8 @@ fn invalid_async_receive_with_retry<F1, F2>(
let route: &[&[&Node]] = &[&[&nodes[1], &nodes[2]]];
let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
.without_claimable_event()
- .expect_failure(HTLCHandlingFailureType::Receive { payment_hash });
+ .expect_failure(HTLCHandlingFailureType::Receive { payment_hash })
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
do_pass_along_path(args);
fail_blinded_htlc_backwards(payment_hash, 1, &[&nodes[0], &nodes[1], &nodes[2]], true);
@@ -1751,7 +1760,8 @@ fn invalid_async_receive_with_retry<F1, F2>(
let mut ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
check_added_monitors!(nodes[0], 1);
let route: &[&[&Node]] = &[&[&nodes[1], &nodes[2]]];
- let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev);
+ let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
let claimable_ev = do_pass_along_path(args).unwrap();
let keysend_preimage = extract_payment_preimage(&claimable_ev);
claim_payment_along_route(ClaimAlongRouteArgs::new(&nodes[0], route, keysend_preimage));
@@ -1858,6 +1868,13 @@ fn expired_static_invoice_payment_path() {
blinded_path
.advance_path_by_one(&nodes[1].keys_manager, &nodes[1].node, &secp_ctx)
.unwrap();
+
+ for _ in 0..DEFAULT_PAYMENT_DUMMY_HOPS {
+ blinded_path
+ .advance_path_by_one(&nodes[2].keys_manager, &nodes[2].node, &secp_ctx)
+ .unwrap();
+ }
+
match blinded_path.decrypt_intro_payload(&nodes[2].keys_manager).unwrap().0 {
BlindedPaymentTlvs::Receive(tlvs) => tlvs.payment_constraints.max_cltv_expiry,
_ => panic!(),
@@ -1920,7 +1937,8 @@ fn expired_static_invoice_payment_path() {
let route: &[&[&Node]] = &[&[&nodes[1], &nodes[2]]];
let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
.without_claimable_event()
- .expect_failure(HTLCHandlingFailureType::Receive { payment_hash });
+ .expect_failure(HTLCHandlingFailureType::Receive { payment_hash })
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
do_pass_along_path(args);
fail_blinded_htlc_backwards(payment_hash, 1, &[&nodes[0], &nodes[1], &nodes[2]], false);
nodes[2].logger.assert_log_contains(
@@ -2363,7 +2381,8 @@ fn refresh_static_invoices_for_used_offers() {
check_added_monitors!(sender, 1);
let route: &[&[&Node]] = &[&[server, recipient]];
- let args = PassAlongPathArgs::new(sender, route[0], amt_msat, payment_hash, ev);
+ let args = PassAlongPathArgs::new(sender, route[0], amt_msat, payment_hash, ev)
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
let claimable_ev = do_pass_along_path(args).unwrap();
let keysend_preimage = extract_payment_preimage(&claimable_ev);
let res = claim_payment_along_route(ClaimAlongRouteArgs::new(sender, route, keysend_preimage));
@@ -2697,7 +2716,8 @@ fn invoice_server_is_not_channel_peer() {
check_added_monitors!(sender, 1);
let route: &[&[&Node]] = &[&[forwarding_node, recipient]];
- let args = PassAlongPathArgs::new(sender, route[0], amt_msat, payment_hash, ev);
+ let args = PassAlongPathArgs::new(sender, route[0], amt_msat, payment_hash, ev)
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
let claimable_ev = do_pass_along_path(args).unwrap();
let keysend_preimage = extract_payment_preimage(&claimable_ev);
let res = claim_payment_along_route(ClaimAlongRouteArgs::new(sender, route, keysend_preimage));
@@ -2936,7 +2956,8 @@ fn async_payment_e2e() {
check_added_monitors!(sender_lsp, 1);
let path: &[&Node] = &[invoice_server, recipient];
- let args = PassAlongPathArgs::new(sender_lsp, path, amt_msat, payment_hash, ev);
+ let args = PassAlongPathArgs::new(sender_lsp, path, amt_msat, payment_hash, ev)
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
let claimable_ev = do_pass_along_path(args).unwrap();
let route: &[&[&Node]] = &[&[sender_lsp, invoice_server, recipient]];
@@ -3173,7 +3194,8 @@ fn intercepted_hold_htlc() {
check_added_monitors!(lsp, 1);
let path: &[&Node] = &[recipient];
- let args = PassAlongPathArgs::new(lsp, path, amt_msat, payment_hash, ev);
+ let args = PassAlongPathArgs::new(lsp, path, amt_msat, payment_hash, ev)
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
let claimable_ev = do_pass_along_path(args).unwrap();
let route: &[&[&Node]] = &[&[lsp, recipient]];
@@ -3276,7 +3298,8 @@ fn async_payment_mpp() {
assert_eq!(events.len(), 1);
let ev = remove_first_msg_event_to_node(&recipient.node.get_our_node_id(), &mut events);
let args = PassAlongPathArgs::new(lsp_a, expected_path, amt_msat, payment_hash, ev)
- .without_claimable_event();
+ .without_claimable_event()
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
do_pass_along_path(args);
lsp_b.node.process_pending_htlc_forwards();
@@ -3284,7 +3307,8 @@ fn async_payment_mpp() {
let mut events = lsp_b.node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
let ev = remove_first_msg_event_to_node(&recipient.node.get_our_node_id(), &mut events);
- let args = PassAlongPathArgs::new(lsp_b, expected_path, amt_msat, payment_hash, ev);
+ let args = PassAlongPathArgs::new(lsp_b, expected_path, amt_msat, payment_hash, ev)
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
let claimable_ev = do_pass_along_path(args).unwrap();
let keysend_preimage = match claimable_ev {
@@ -3420,7 +3444,8 @@ fn release_htlc_races_htlc_onion_decode() {
check_added_monitors!(sender_lsp, 1);
let path: &[&Node] = &[invoice_server, recipient];
- let args = PassAlongPathArgs::new(sender_lsp, path, amt_msat, payment_hash, ev);
+ let args = PassAlongPathArgs::new(sender_lsp, path, amt_msat, payment_hash, ev)
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
let claimable_ev = do_pass_along_path(args).unwrap();
let route: &[&[&Node]] = &[&[sender_lsp, invoice_server, recipient]];
diff --git a/lightning/src/ln/offers_tests.rs b/lightning/src/ln/offers_tests.rs
index 0b2d5b8..cd24c2d 100644
--- a/lightning/src/ln/offers_tests.rs
+++ b/lightning/src/ln/offers_tests.rs
@@ -47,7 +47,7 @@ use bitcoin::secp256k1::{PublicKey, Secp256k1};
use core::time::Duration;
use crate::blinded_path::IntroductionNode;
use crate::blinded_path::message::BlindedMessagePath;
-use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext};
+use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, DummyTlvs, PaymentContext};
use crate::blinded_path::message::OffersContext;
use crate::events::{ClosureReason, Event, HTLCHandlingFailureType, PaidBolt12Invoice, PaymentFailureReason, PaymentPurpose};
use crate::ln::channelmanager::{Bolt12PaymentError, PaymentId, RecentPaymentDetails, RecipientOnionFields, Retry, self};
@@ -63,7 +63,7 @@ use crate::offers::parse::Bolt12SemanticError;
use crate::onion_message::messenger::{DefaultMessageRouter, Destination, MessageSendInstructions, NodeIdMessageRouter, NullMessageRouter, PeeledOnion, PADDED_PATH_LENGTH};
use crate::onion_message::offers::OffersMessage;
use crate::routing::gossip::{NodeAlias, NodeId};
-use crate::routing::router::{PaymentParameters, RouteParameters, RouteParametersConfig};
+use crate::routing::router::{DEFAULT_PAYMENT_DUMMY_HOPS, PaymentParameters, RouteParameters, RouteParametersConfig};
use crate::sign::{NodeSigner, Recipient};
use crate::util::ser::Writeable;
@@ -178,7 +178,8 @@ fn route_bolt12_payment<'a, 'b, 'c>(
let amount_msats = invoice.amount_msats();
let payment_hash = invoice.payment_hash();
let args = PassAlongPathArgs::new(node, path, amount_msats, payment_hash, ev)
- .without_clearing_recipient_events();
+ .without_clearing_recipient_events()
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
do_pass_along_path(args);
}
@@ -1432,7 +1433,20 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() {
route_bolt12_payment(bob, &[alice], &invoice);
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
- claim_bolt12_payment(bob, &[alice], payment_context, &invoice);
+ // When the payer is the introduction node of a blinded path, LDK doesn't
+ // subtract the forward fee for the `payer -> next_hop` channel (see
+ // `BlindedPaymentPath::advance_path_by_one`). This keeps fee logic simple,
+ // at the cost of a small, intentional overpayment.
+ //
+ // In the old two-hop case (payer as introduction node → payee), this never
+ // surfaced because the payer simply wasn’t charged the forward fee.
+ //
+ // With dummy hops in LDK v0.3, even a real two-node path can appear as a
+ // longer blinded route, so the overpayment shows up in tests.
+ //
+ // Until the fee-handling trade-off is revisited, we pass an expected extra
+ // fee here so tests can compensate for it.
+ claim_bolt12_payment_with_extra_fees(bob, &[alice], payment_context, &invoice, Some(1000));
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
}
@@ -2444,12 +2458,13 @@ fn rejects_keysend_to_non_static_invoice_path() {
let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
.with_payment_preimage(payment_preimage)
- .expect_failure(HTLCHandlingFailureType::Receive { payment_hash });
+ .expect_failure(HTLCHandlingFailureType::Receive { payment_hash })
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
do_pass_along_path(args);
let mut updates = get_htlc_update_msgs(&nodes[1], &nodes[0].node.get_our_node_id());
- nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
+ nodes[0].node.handle_update_fail_malformed_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_malformed_htlcs[0]);
do_commitment_signed_dance(&nodes[0], &nodes[1], &updates.commitment_signed, false, false);
- expect_payment_failed_conditions(&nodes[0], payment_hash, true, PaymentFailedConditions::new());
+ expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new());
}
#[test]
@@ -2508,12 +2523,14 @@ fn no_double_pay_with_stale_channelmanager() {
let ev = remove_first_msg_event_to_node(&bob_id, &mut events);
let args = PassAlongPathArgs::new(&nodes[0], expected_route[0], amt_msat, payment_hash, ev)
- .without_clearing_recipient_events();
+ .without_clearing_recipient_events()
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
do_pass_along_path(args);
let ev = remove_first_msg_event_to_node(&bob_id, &mut events);
let args = PassAlongPathArgs::new(&nodes[0], expected_route[0], amt_msat, payment_hash, ev)
- .without_clearing_recipient_events();
+ .without_clearing_recipient_events()
+ .with_dummy_tlvs(&[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS]);
do_pass_along_path(args);
expect_recent_payment!(nodes[0], RecentPaymentDetails::Pending, payment_id);
diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs
index c06e517..cb1b3d0 100644
--- a/lightning/src/routing/router.rs
+++ b/lightning/src/routing/router.rs
@@ -13,8 +13,8 @@ use bitcoin::secp256k1::{self, PublicKey, Secp256k1};
use lightning_invoice::Bolt11Invoice;
use crate::blinded_path::payment::{
- BlindedPaymentPath, ForwardTlvs, PaymentConstraints, PaymentForwardNode, PaymentRelay,
- ReceiveTlvs,
+ BlindedPaymentPath, DummyTlvs, ForwardTlvs, PaymentConstraints, PaymentForwardNode,
+ PaymentRelay, ReceiveTlvs,
};
use crate::blinded_path::{BlindedHop, Direction, IntroductionNode};
use crate::crypto::chacha20::ChaCha20;
@@ -74,6 +74,9 @@ pub struct DefaultRouter<
score_params: SP,
}
+/// The number of dummy hops included in [`BlindedPaymentPath`]s created by [`DefaultRouter`].
+pub const DEFAULT_PAYMENT_DUMMY_HOPS: usize = 3;
+
impl<
G: Deref<Target = NetworkGraph<L>>,
L: Deref,
@@ -198,9 +201,9 @@ where
})
})
.map(|forward_node| {
- BlindedPaymentPath::new(
- &[forward_node], recipient, local_node_receive_key, tlvs.clone(), u64::MAX, MIN_FINAL_CLTV_EXPIRY_DELTA,
- &*self.entropy_source, secp_ctx
+ BlindedPaymentPath::new_with_dummy_hops(
+ &[forward_node], recipient, &[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS],
+ local_node_receive_key, tlvs.clone(), u64::MAX, MIN_FINAL_CLTV_EXPIRY_DELTA, &*self.entropy_source, secp_ctx
)
})
.take(MAX_PAYMENT_PATHS)
@@ -210,9 +213,9 @@ where
Ok(paths) if !paths.is_empty() => Ok(paths),
_ => {
if network_graph.nodes().contains_key(&NodeId::from_pubkey(&recipient)) {
- BlindedPaymentPath::new(
- &[], recipient, local_node_receive_key, tlvs, u64::MAX, MIN_FINAL_CLTV_EXPIRY_DELTA, &*self.entropy_source,
- secp_ctx
+ BlindedPaymentPath::new_with_dummy_hops(
+ &[], recipient, &[DummyTlvs::default(); DEFAULT_PAYMENT_DUMMY_HOPS],
+ local_node_receive_key, tlvs, u64::MAX, MIN_FINAL_CLTV_EXPIRY_DELTA, &*self.entropy_source, secp_ctx
).map(|path| vec![path])
} else {
Err(())
Why this scored 34/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.