X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Frouter.rs;h=1dbd1ffc655569187459d45e822803839a9eda0e;hb=27e55190322546c639e0aefc0363e2f892d22677;hp=485fd239128df8ab39b0806723a7d3d6b6e24e3a;hpb=ea5de93dd9e646124c13fd5c3da4150d3b9eb9f7;p=rust-lightning diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 485fd239..1dbd1ffc 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -26,7 +26,7 @@ use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp}; use crate::sign::EntropySource; use crate::util::ser::{Writeable, Readable, ReadableArgs, Writer}; use crate::util::logger::{Level, Logger}; -use crate::util::chacha20::ChaCha20; +use crate::crypto::chacha20::ChaCha20; use crate::io; use crate::prelude::*; @@ -114,19 +114,14 @@ impl> + Clone, L: Deref, S: Deref, SP: Sized, None => return None, }; let payment_relay: PaymentRelay = match details.counterparty.forwarding_info { - Some(forwarding_info) => forwarding_info.into(), + Some(forwarding_info) => match forwarding_info.try_into() { + Ok(payment_relay) => payment_relay, + Err(()) => return None, + }, None => return None, }; - // Avoid exposing esoteric CLTV expiry deltas - let cltv_expiry_delta = match payment_relay.cltv_expiry_delta { - 0..=40 => 40u32, - 41..=80 => 80u32, - 81..=144 => 144u32, - 145..=216 => 216u32, - _ => return None, - }; - + let cltv_expiry_delta = payment_relay.cltv_expiry_delta as u32; let payment_constraints = PaymentConstraints { max_cltv_expiry: tlvs.payment_constraints.max_cltv_expiry + cltv_expiry_delta, htlc_minimum_msat: details.inbound_htlc_minimum_msat.unwrap_or(0), @@ -513,20 +508,20 @@ impl Writeable for Route { write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION); (self.paths.len() as u64).write(writer)?; let mut blinded_tails = Vec::new(); - for path in self.paths.iter() { + for (idx, path) in self.paths.iter().enumerate() { (path.hops.len() as u8).write(writer)?; - for (idx, hop) in path.hops.iter().enumerate() { + for hop in path.hops.iter() { hop.write(writer)?; - if let Some(blinded_tail) = &path.blinded_tail { - if blinded_tails.is_empty() { - blinded_tails = Vec::with_capacity(path.hops.len()); - for _ in 0..idx { - blinded_tails.push(None); - } - } - blinded_tails.push(Some(blinded_tail)); - } else if !blinded_tails.is_empty() { blinded_tails.push(None); } } + if let Some(blinded_tail) = &path.blinded_tail { + if blinded_tails.is_empty() { + blinded_tails = Vec::with_capacity(path.hops.len()); + for _ in 0..idx { + blinded_tails.push(None); + } + } + blinded_tails.push(Some(blinded_tail)); + } else if !blinded_tails.is_empty() { blinded_tails.push(None); } } write_tlv_fields!(writer, { // For compatibility with LDK versions prior to 0.0.117, we take the individual @@ -534,7 +529,7 @@ impl Writeable for Route { (1, self.route_params.as_ref().map(|p| &p.payment_params), option), (2, blinded_tails, optional_vec), (3, self.route_params.as_ref().map(|p| p.final_value_msat), option), - (5, self.route_params.as_ref().map(|p| p.max_total_routing_fee_msat), option), + (5, self.route_params.as_ref().and_then(|p| p.max_total_routing_fee_msat), option), }); Ok(()) } @@ -711,6 +706,11 @@ pub struct PaymentParameters { /// payment to fail. Future attempts for the same payment shouldn't be relayed through any of /// these SCIDs. pub previously_failed_channels: Vec, + + /// A list of indices corresponding to blinded paths in [`Payee::Blinded::route_hints`] which this + /// payment was previously attempted over and which caused the payment to fail. Future attempts + /// for the same payment shouldn't be relayed through any of these blinded paths. + pub previously_failed_blinded_path_idxs: Vec, } impl Writeable for PaymentParameters { @@ -732,6 +732,7 @@ impl Writeable for PaymentParameters { (7, self.previously_failed_channels, required_vec), (8, *blinded_hints, optional_vec), (9, self.payee.final_cltv_expiry_delta(), option), + (11, self.previously_failed_blinded_path_idxs, required_vec), }); Ok(()) } @@ -750,6 +751,7 @@ impl ReadableArgs for PaymentParameters { (7, previously_failed_channels, optional_vec), (8, blinded_route_hints, optional_vec), (9, final_cltv_expiry_delta, (default_value, default_final_cltv_expiry_delta)), + (11, previously_failed_blinded_path_idxs, optional_vec), }); let blinded_route_hints = blinded_route_hints.unwrap_or(vec![]); let payee = if blinded_route_hints.len() != 0 { @@ -773,6 +775,7 @@ impl ReadableArgs for PaymentParameters { max_channel_saturation_power_of_half: _init_tlv_based_struct_field!(max_channel_saturation_power_of_half, (default_value, unused)), expiry_time, previously_failed_channels: previously_failed_channels.unwrap_or(Vec::new()), + previously_failed_blinded_path_idxs: previously_failed_blinded_path_idxs.unwrap_or(Vec::new()), }) } } @@ -791,6 +794,7 @@ impl PaymentParameters { max_path_count: DEFAULT_MAX_PATH_COUNT, max_channel_saturation_power_of_half: DEFAULT_MAX_CHANNEL_SATURATION_POW_HALF, previously_failed_channels: Vec::new(), + previously_failed_blinded_path_idxs: Vec::new(), } } @@ -829,6 +833,7 @@ impl PaymentParameters { max_path_count: DEFAULT_MAX_PATH_COUNT, max_channel_saturation_power_of_half: DEFAULT_MAX_CHANNEL_SATURATION_POW_HALF, previously_failed_channels: Vec::new(), + previously_failed_blinded_path_idxs: Vec::new(), } } @@ -904,6 +909,19 @@ impl PaymentParameters { pub fn with_max_channel_saturation_power_of_half(self, max_channel_saturation_power_of_half: u8) -> Self { Self { max_channel_saturation_power_of_half, ..self } } + + pub(crate) fn insert_previously_failed_blinded_path(&mut self, failed_blinded_tail: &BlindedTail) { + let mut found_blinded_tail = false; + for (idx, (_, path)) in self.payee.blinded_route_hints().iter().enumerate() { + if failed_blinded_tail.hops == path.blinded_hops && + failed_blinded_tail.blinding_point == path.blinding_point + { + self.previously_failed_blinded_path_idxs.push(idx as u64); + found_blinded_tail = true; + } + } + debug_assert!(found_blinded_tail); + } } /// The recipient of a payment, differing based on whether they've hidden their identity with route @@ -1360,6 +1378,15 @@ impl<'a> CandidateRouteHop<'a> { _ => None, } } + fn blinded_hint_idx(&self) -> Option { + match self { + Self::Blinded(BlindedPathCandidate { hint_idx, .. }) | + Self::OneHopBlinded(OneHopBlindedPathCandidate { hint_idx, .. }) => { + Some(*hint_idx) + }, + _ => None, + } + } /// Returns the source node id of current hop. /// /// Source node id refers to the node forwarding the HTLC through this hop. @@ -2111,8 +2138,15 @@ where L::Target: Logger { (amount_to_transfer_over_msat < $next_hops_path_htlc_minimum_msat && recommended_value_msat >= $next_hops_path_htlc_minimum_msat)); - let payment_failed_on_this_channel = scid_opt.map_or(false, - |scid| payment_params.previously_failed_channels.contains(&scid)); + let payment_failed_on_this_channel = match scid_opt { + Some(scid) => payment_params.previously_failed_channels.contains(&scid), + None => match $candidate.blinded_hint_idx() { + Some(idx) => { + payment_params.previously_failed_blinded_path_idxs.contains(&(idx as u64)) + }, + None => false, + }, + }; let (should_log_candidate, first_hop_details) = match $candidate { CandidateRouteHop::FirstHop(hop) => (true, Some(hop.details)), @@ -3195,7 +3229,7 @@ mod tests { use crate::offers::invoice::BlindedPayInfo; use crate::util::config::UserConfig; use crate::util::test_utils as ln_test_utils; - use crate::util::chacha20::ChaCha20; + use crate::crypto::chacha20::ChaCha20; use crate::util::ser::{Readable, Writeable}; #[cfg(c_bindings)] use crate::util::ser::Writer;