Skip to content

Commit f0b5c58

Browse files
outbound_payment: set max path length in PaymentParameters.
So the router knows how long the maximum payment path can be.
1 parent c6de5e1 commit f0b5c58

File tree

3 files changed

+93
-3
lines changed

3 files changed

+93
-3
lines changed

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,10 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) {
282282

283283
let amt_msat = 5000;
284284
let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None);
285-
let route_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000,
285+
let mut route_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000,
286286
nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(),
287287
&[&chan_upd_1_2, &chan_upd_2_3], &chanmon_cfgs[3].keys_manager);
288+
route_params.payment_params.max_path_length = 18;
288289

289290
let route = get_route(&nodes[0], &route_params).unwrap();
290291
node_cfgs[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));

lightning/src/ln/onion_utils.rs

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010
use crate::blinded_path::BlindedHop;
1111
use crate::crypto::chacha20::ChaCha20;
1212
use crate::crypto::streams::ChaChaReader;
13+
use crate::ln::channel::TOTAL_BITCOIN_SUPPLY_SATOSHIS;
1314
use crate::ln::channelmanager::{HTLCSource, RecipientOnionFields};
15+
use crate::ln::features::{ChannelFeatures, NodeFeatures};
1416
use crate::ln::msgs;
1517
use crate::ln::types::{PaymentHash, PaymentPreimage};
1618
use crate::ln::wire::Encode;
1719
use crate::routing::gossip::NetworkUpdate;
18-
use crate::routing::router::{Path, RouteHop};
20+
use crate::routing::router::{Path, RouteHop, RouteParameters};
1921
use crate::sign::NodeSigner;
2022
use crate::util::errors::{self, APIError};
2123
use crate::util::logger::Logger;
@@ -310,6 +312,77 @@ where
310312
Ok((cur_value_msat, cur_cltv))
311313
}
312314

315+
pub(crate) const MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY: u64 = 100_000_000;
316+
317+
pub(crate) fn set_max_path_length(
318+
route_params: &mut RouteParameters, recipient_onion: &RecipientOnionFields,
319+
keysend_preimage: Option<PaymentPreimage>, best_block_height: u32,
320+
) -> Result<(), ()> {
321+
const PAYLOAD_HMAC_LEN: usize = 32;
322+
let unblinded_intermed_payload_len = msgs::OutboundOnionPayload::Forward {
323+
short_channel_id: 42,
324+
amt_to_forward: TOTAL_BITCOIN_SUPPLY_SATOSHIS,
325+
outgoing_cltv_value: route_params.payment_params.max_total_cltv_expiry_delta,
326+
}
327+
.serialized_length()
328+
.saturating_add(PAYLOAD_HMAC_LEN);
329+
330+
const OVERPAY_ESTIMATE_MULTIPLER: u64 = 3;
331+
let final_value_msat_with_overpay_buffer = core::cmp::max(
332+
route_params.final_value_msat.saturating_mul(OVERPAY_ESTIMATE_MULTIPLER),
333+
MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY,
334+
);
335+
336+
let blinded_tail_opt = route_params
337+
.payment_params
338+
.payee
339+
.blinded_route_hints()
340+
.iter()
341+
.map(|(_, path)| path)
342+
.max_by_key(|path| path.serialized_length())
343+
.map(|largest_path| BlindedTailHopIter {
344+
hops: largest_path.blinded_hops.iter(),
345+
blinding_point: largest_path.blinding_point,
346+
final_value_msat: final_value_msat_with_overpay_buffer,
347+
excess_final_cltv_expiry_delta: 0,
348+
});
349+
350+
let unblinded_route_hop = RouteHop {
351+
pubkey: PublicKey::from_slice(&[2; 33]).unwrap(),
352+
node_features: NodeFeatures::empty(),
353+
short_channel_id: 42,
354+
channel_features: ChannelFeatures::empty(),
355+
fee_msat: final_value_msat_with_overpay_buffer,
356+
cltv_expiry_delta: route_params.payment_params.max_total_cltv_expiry_delta,
357+
maybe_announced_channel: false,
358+
};
359+
let mut num_reserved_bytes: usize = 0;
360+
let build_payloads_res = build_onion_payloads_callback(
361+
core::iter::once(&unblinded_route_hop),
362+
blinded_tail_opt,
363+
final_value_msat_with_overpay_buffer,
364+
&recipient_onion,
365+
best_block_height,
366+
&keysend_preimage,
367+
|_, payload| {
368+
num_reserved_bytes = num_reserved_bytes
369+
.saturating_add(payload.serialized_length())
370+
.saturating_add(PAYLOAD_HMAC_LEN);
371+
},
372+
);
373+
debug_assert!(build_payloads_res.is_ok());
374+
375+
let max_path_length = 1300usize
376+
.checked_sub(num_reserved_bytes)
377+
.map(|p| p / unblinded_intermed_payload_len)
378+
.and_then(|l| u8::try_from(l.saturating_add(1)).ok())
379+
.ok_or(())?;
380+
381+
route_params.payment_params.max_path_length =
382+
core::cmp::min(max_path_length, route_params.payment_params.max_path_length);
383+
Ok(())
384+
}
385+
313386
/// Length of the onion data packet. Before TLV-based onions this was 20 65-byte hops, though now
314387
/// the hops can be of variable length.
315388
pub(crate) const ONION_DATA_LEN: usize = 20 * 65;

lightning/src/ln/outbound_payment.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::sign::{EntropySource, NodeSigner, Recipient};
1717
use crate::events::{self, PaymentFailureReason};
1818
use crate::ln::types::{PaymentHash, PaymentPreimage, PaymentSecret};
1919
use crate::ln::channelmanager::{ChannelDetails, EventCompletionAction, HTLCSource, PaymentId};
20+
use crate::ln::onion_utils;
2021
use crate::ln::onion_utils::{DecodedOnionFailure, HTLCFailReason};
2122
use crate::offers::invoice::Bolt12Invoice;
2223
use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteParameters, Router};
@@ -421,6 +422,12 @@ pub enum RetryableSendFailure {
421422
/// [`Event::PaymentSent`]: crate::events::Event::PaymentSent
422423
/// [`Event::PaymentFailed`]: crate::events::Event::PaymentFailed
423424
DuplicatePayment,
425+
/// The [`RecipientOnionFields::payment_metadata`], [`RecipientOnionFields::custom_tlvs`], or
426+
/// [`BlindedPath`]s provided are too large and caused us to exceed the maximum onion packet size
427+
/// of 1300 bytes.
428+
///
429+
/// [`BlindedPath`]: crate::blinded_path::BlindedPath
430+
OnionPacketSizeExceeded,
424431
}
425432

426433
/// If a payment fails to send with [`ChannelManager::send_payment_with_route`], it can be in one
@@ -886,7 +893,7 @@ impl OutboundPayments {
886893
/// [`Event::PaymentFailed`]: crate::events::Event::PaymentFailed
887894
fn send_payment_internal<R: Deref, NS: Deref, ES: Deref, IH, SP, L: Deref>(
888895
&self, payment_id: PaymentId, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields,
889-
keysend_preimage: Option<PaymentPreimage>, retry_strategy: Retry, route_params: RouteParameters,
896+
keysend_preimage: Option<PaymentPreimage>, retry_strategy: Retry, mut route_params: RouteParameters,
890897
router: &R, first_hops: Vec<ChannelDetails>, inflight_htlcs: IH, entropy_source: &ES,
891898
node_signer: &NS, best_block_height: u32, logger: &L,
892899
pending_events: &Mutex<VecDeque<(events::Event, Option<EventCompletionAction>)>>, send_payment_along_path: SP,
@@ -907,6 +914,15 @@ impl OutboundPayments {
907914
}
908915
}
909916

917+
onion_utils::set_max_path_length(
918+
&mut route_params, &recipient_onion, keysend_preimage, best_block_height
919+
)
920+
.map_err(|()| {
921+
log_error!(logger, "Can't construct an onion packet without exceeding 1300-byte onion \
922+
hop_data length for payment with id {} and hash {}", payment_id, payment_hash);
923+
RetryableSendFailure::OnionPacketSizeExceeded
924+
})?;
925+
910926
let mut route = router.find_route_with_id(
911927
&node_signer.get_node_id(Recipient::Node).unwrap(), &route_params,
912928
Some(&first_hops.iter().collect::<Vec<_>>()), inflight_htlcs(),

0 commit comments

Comments
 (0)