Merge pull request #2515 from TheBlueMatt/2023-08-earlier-payment-hash-log
[rust-lightning] / lightning / src / routing / router.rs
index caba139103249179228738a6aa7bca3c0e54c378..ded4a5595608c1343ad16bf569cf9f32b6ae0d23 100644 (file)
@@ -425,7 +425,7 @@ impl Readable for Route {
                                cmp::min(min_final_cltv_expiry_delta, hops.last().unwrap().cltv_expiry_delta);
                        paths.push(Path { hops, blinded_tail: None });
                }
-               _init_and_read_tlv_fields!(reader, {
+               _init_and_read_len_prefixed_tlv_fields!(reader, {
                        (1, payment_params, (option: ReadableArgs, min_final_cltv_expiry_delta)),
                        (2, blinded_tails, optional_vec),
                });
@@ -467,7 +467,7 @@ impl Writeable for RouteParameters {
 
 impl Readable for RouteParameters {
        fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
-               _init_and_read_tlv_fields!(reader, {
+               _init_and_read_len_prefixed_tlv_fields!(reader, {
                        (0, payment_params, (required: ReadableArgs, 0)),
                        (2, final_value_msat, required),
                        (4, final_cltv_delta, option),
@@ -575,7 +575,7 @@ impl Writeable for PaymentParameters {
 
 impl ReadableArgs<u32> for PaymentParameters {
        fn read<R: io::Read>(reader: &mut R, default_final_cltv_expiry_delta: u32) -> Result<Self, DecodeError> {
-               _init_and_read_tlv_fields!(reader, {
+               _init_and_read_len_prefixed_tlv_fields!(reader, {
                        (0, payee_pubkey, option),
                        (1, max_total_cltv_expiry_delta, (default_value, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA)),
                        (2, features, (option: ReadableArgs, payee_pubkey.is_some())),
@@ -652,11 +652,12 @@ impl PaymentParameters {
        /// [`PaymentParameters::expiry_time`].
        pub fn from_bolt12_invoice(invoice: &Bolt12Invoice) -> Self {
                Self::blinded(invoice.payment_paths().to_vec())
-                       .with_bolt12_features(invoice.features().clone()).unwrap()
+                       .with_bolt12_features(invoice.invoice_features().clone()).unwrap()
                        .with_expiry_time(invoice.created_at().as_secs().saturating_add(invoice.relative_expiry().as_secs()))
        }
 
-       fn blinded(blinded_route_hints: Vec<(BlindedPayInfo, BlindedPath)>) -> Self {
+       /// Creates parameters for paying to a blinded payee from the provided blinded route hints.
+       pub fn blinded(blinded_route_hints: Vec<(BlindedPayInfo, BlindedPath)>) -> Self {
                Self {
                        payee: Payee::Blinded { route_hints: blinded_route_hints, features: None },
                        expiry_time: None,
@@ -1333,6 +1334,14 @@ impl<'a> fmt::Display for LoggedCandidateHop<'a> {
                                " and blinding point ".fmt(f)?;
                                hint.1.blinding_point.fmt(f)
                        },
+                       CandidateRouteHop::FirstHop { .. } => {
+                               "first hop with SCID ".fmt(f)?;
+                               self.0.short_channel_id().unwrap().fmt(f)
+                       },
+                       CandidateRouteHop::PrivateHop { .. } => {
+                               "route hint with SCID ".fmt(f)?;
+                               self.0.short_channel_id().unwrap().fmt(f)
+                       },
                        _ => {
                                "SCID ".fmt(f)?;
                                self.0.short_channel_id().unwrap().fmt(f)
@@ -1640,6 +1649,12 @@ where L::Target: Logger {
        log_trace!(logger, "Building path from {} to payer {} for value {} msat.",
                LoggedPayeePubkey(payment_params.payee.node_id()), our_node_pubkey, final_value_msat);
 
+       // Remember how many candidates we ignored to allow for some logging afterwards.
+       let mut num_ignored_value_contribution = 0;
+       let mut num_ignored_path_length_limit = 0;
+       let mut num_ignored_cltv_delta_limit = 0;
+       let mut num_ignored_previously_failed = 0;
+
        macro_rules! add_entry {
                // Adds entry which goes from $src_node_id to $dest_node_id over the $candidate hop.
                // $next_hops_fee_msat represents the fees paid for using all the channels *after* this one,
@@ -1714,13 +1729,37 @@ where L::Target: Logger {
                                        let payment_failed_on_this_channel = scid_opt.map_or(false,
                                                |scid| payment_params.previously_failed_channels.contains(&scid));
 
+                                       let should_log_candidate = match $candidate {
+                                               CandidateRouteHop::FirstHop { .. } => true,
+                                               CandidateRouteHop::PrivateHop { .. } => true,
+                                               CandidateRouteHop::Blinded { .. } => true,
+                                               _ => false,
+                                       };
+
                                        // If HTLC minimum is larger than the amount we're going to transfer, we shouldn't
                                        // bother considering this channel. If retrying with recommended_value_msat may
                                        // allow us to hit the HTLC minimum limit, set htlc_minimum_limit so that we go
                                        // around again with a higher amount.
-                                       if !contributes_sufficient_value || exceeds_max_path_length ||
-                                               exceeds_cltv_delta_limit || payment_failed_on_this_channel {
-                                               // Path isn't useful, ignore it and move on.
+                                       if !contributes_sufficient_value {
+                                               if should_log_candidate {
+                                                       log_trace!(logger, "Ignoring {} due to insufficient value contribution.", LoggedCandidateHop(&$candidate));
+                                               }
+                                               num_ignored_value_contribution += 1;
+                                       } else if exceeds_max_path_length {
+                                               if should_log_candidate {
+                                                       log_trace!(logger, "Ignoring {} due to exceeding maximum path length limit.", LoggedCandidateHop(&$candidate));
+                                               }
+                                               num_ignored_path_length_limit += 1;
+                                       } else if exceeds_cltv_delta_limit {
+                                               if should_log_candidate {
+                                                       log_trace!(logger, "Ignoring {} due to exceeding CLTV delta limit.", LoggedCandidateHop(&$candidate));
+                                               }
+                                               num_ignored_cltv_delta_limit += 1;
+                                       } else if payment_failed_on_this_channel {
+                                               if should_log_candidate {
+                                                       log_trace!(logger, "Ignoring {} due to a failed previous payment attempt.", LoggedCandidateHop(&$candidate));
+                                               }
+                                               num_ignored_previously_failed += 1;
                                        } else if may_overpay_to_meet_path_minimum_msat {
                                                hit_minimum_limit = true;
                                        } else if over_path_minimum_msat {
@@ -2322,6 +2361,12 @@ where L::Target: Logger {
                }
        }
 
+       let num_ignored_total = num_ignored_value_contribution + num_ignored_path_length_limit +
+               num_ignored_cltv_delta_limit + num_ignored_previously_failed;
+       if num_ignored_total > 0 {
+               log_trace!(logger, "Ignored {} candidate hops due to insufficient value contribution, {} due to path length limit, {} due to CLTV delta limit, {} due to previous payment failure. Total: {} ignored candidates.", num_ignored_value_contribution, num_ignored_path_length_limit, num_ignored_cltv_delta_limit, num_ignored_previously_failed, num_ignored_total);
+       }
+
        // Step (5).
        if payment_paths.len() == 0 {
                return Err(LightningError{err: "Failed to find a path to the given destination".to_owned(), action: ErrorAction::IgnoreError});
@@ -2680,7 +2725,6 @@ mod tests {
                        inbound_scid_alias: None,
                        channel_value_satoshis: 0,
                        user_channel_id: 0,
-                       balance_msat: 0,
                        outbound_capacity_msat,
                        next_outbound_htlc_limit_msat: outbound_capacity_msat,
                        next_outbound_htlc_minimum_msat: 0,
@@ -6749,7 +6793,6 @@ pub(crate) mod bench_utils {
                        outbound_scid_alias: None,
                        channel_value_satoshis: 10_000_000_000,
                        user_channel_id: 0,
-                       balance_msat: 10_000_000_000,
                        outbound_capacity_msat: 10_000_000_000,
                        next_outbound_htlc_minimum_msat: 0,
                        next_outbound_htlc_limit_msat: 10_000_000_000,