From: Valentine Wallace Date: Thu, 14 Sep 2023 15:46:02 +0000 (-0400) Subject: Fix PaymentPathFailed::payment_failed_permanently on blinded path fail X-Git-Tag: v0.0.117-alpha2~8^2~1 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=9df61dc0b8d74f9323d0a25bf7b7ca2f9ab48f1c;p=rust-lightning 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. --- diff --git a/lightning/src/ln/onion_utils.rs b/lightning/src/ln/onion_utils.rs index 4b5ccfe9..f3f86086 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