From 9df61dc0b8d74f9323d0a25bf7b7ca2f9ab48f1c Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Thu, 14 Sep 2023 11:46:02 -0400 Subject: [PATCH] Fix PaymentPathFailed::payment_failed_permanently on blinded path fail Previously this value would be incorrectly set to true because we wouldn't account for blinded hops when determining if we were processing the last hop's failure packet. --- lightning/src/ln/onion_utils.rs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/lightning/src/ln/onion_utils.rs b/lightning/src/ln/onion_utils.rs index 4b5ccfe92..f3f860860 100644 --- a/lightning/src/ln/onion_utils.rs +++ b/lightning/src/ln/onion_utils.rs @@ -481,6 +481,26 @@ pub(super) fn process_onion_failure( }, }; + // The failing hop includes either the inbound channel to the recipient or the outbound channel + // from the current hop (i.e., the next hop's inbound channel). + let num_blinded_hops = path.blinded_tail.as_ref().map_or(0, |bt| bt.hops.len()); + // For 1-hop blinded paths, the final `path.hops` entry is the recipient. + is_from_final_node = route_hop_idx + 1 == path.hops.len() && num_blinded_hops <= 1; + let failing_route_hop = if is_from_final_node { route_hop } else { + match path.hops.get(route_hop_idx + 1) { + Some(hop) => hop, + None => { + // The failing hop is within a multi-hop blinded path. + error_code_ret = Some(BADONION | PERM | 24); // invalid_onion_blinding + error_packet_ret = Some(vec![0; 32]); + res = Some(FailureLearnings { + network_update: None, short_channel_id: None, payment_failed_permanently: false + }); + return + } + } + }; + let amt_to_forward = htlc_msat - route_hop.fee_msat; htlc_msat = amt_to_forward; @@ -492,11 +512,6 @@ pub(super) fn process_onion_failure( chacha.process(&packet_decrypted, &mut decryption_tmp[..]); packet_decrypted = decryption_tmp; - // The failing hop includes either the inbound channel to the recipient or the outbound channel - // from the current hop (i.e., the next hop's inbound channel). - is_from_final_node = route_hop_idx + 1 == path.hops.len(); - let failing_route_hop = if is_from_final_node { route_hop } else { &path.hops[route_hop_idx + 1] }; - let err_packet = match msgs::DecodedOnionErrorPacket::read(&mut Cursor::new(&packet_decrypted)) { Ok(p) => p, Err(_) => return -- 2.39.5