Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate routing errors up to send_payment_for_bolt12_invoice #3159

Closed
tnull opened this issue Jul 4, 2024 · 8 comments · Fixed by #3171
Closed

Propagate routing errors up to send_payment_for_bolt12_invoice #3159

tnull opened this issue Jul 4, 2024 · 8 comments · Fixed by #3171
Assignees
Labels
Take a Friday Leave a Friday Stomp the Bugs, Without Much Commitment

Comments

@tnull
Copy link
Contributor

tnull commented Jul 4, 2024

1. When sending a payment via the async BOLT12 flow introduced in #3078, we would log-and-swallow any path finding errors and silently abandon the payment:

log_error!(logger, "Failed to find a route on retry, abandoning payment {}: {:#?}", &payment_id, e);
self.abandon_payment(payment_id, PaymentFailureReason::RouteNotFound, pending_events);
return

In order to tell the user what went wrong, it would be great to bubble up the Err from find_route_and_send_payment rather than continuing and returning Ok(()).

~~2. We should also early-abort sending in the regular pay_for_offer flow if we're certain we don't have sufficient liquidity (i.e. the offer amount surpasses the sum of our available next_outbound_htlc_limit_msats) ~~

@TheBlueMatt TheBlueMatt added the Take a Friday Leave a Friday Stomp the Bugs, Without Much Commitment label Jul 8, 2024
@jkczyz
Copy link
Contributor

jkczyz commented Jul 9, 2024

I'll likely need to fix this as part of addressing #3085 (comment). Question is how should we structure the error type. Currently, we have:

/// An error when attempting to pay a [`Bolt12Invoice`].
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Bolt12PaymentError {
/// The invoice was not requested.
UnexpectedInvoice,
/// Payment for an invoice with the corresponding [`PaymentId`] was already initiated.
DuplicateInvoice,
/// The [`BlindedPath`]s provided are too large and caused us to exceed the maximum onion hop data
/// size of 1300 bytes.
///
/// [`BlindedPath`]: crate::blinded_path::BlindedPath
OnionPacketSizeExceeded,
}

We could expand this to include a variant for PaymentFailureReason. But there are other places where we return Ok when we may want to return an error. For instance, payment id not found, abandoned, or fulfilled already. Though maybe we should refactor this to hold the lock prior to calling find_route_and_send_payment. This would eliminate those errors and possibly eliminate the need for PendingOutboundPayment::InvoiceReceived. Thoughts?

@jkczyz
Copy link
Contributor

jkczyz commented Jul 9, 2024

Though maybe we should refactor this to hold the lock prior to calling find_route_and_send_payment. This would eliminate those errors and possibly eliminate the need for PendingOutboundPayment::InvoiceReceived. Thoughts?

Hmm... but that would mean we'd need to hold the lock while calling find_route.

@slanesuke
Copy link
Contributor

@jkczyz if you want, I could take this off your hands!? I can expand the Bolt12PaymentError to include a PaymentFailureReason variant and handle the places Ok is returned with more descriptive errors. Also, in pay_for_offer abort the payment if the offer amount > the available channel liquidity. If that's the approach you'd be okay with 👍

@jkczyz
Copy link
Contributor

jkczyz commented Jul 10, 2024

@jkczyz if you want, I could take this off your hands!? I can expand the Bolt12PaymentError to include a PaymentFailureReason variant and handle the places Ok is returned with more descriptive errors. Also, in pay_for_offer abort the payment if the offer amount > the available channel liquidity. If that's the approach you'd be okay with 👍

Discussing with @TheBlueMatt offline. Doesn't seem like this is the right approach. Instead, we need to refactor the code such that:

  • send_payment_for_bolt12_invoice calls pay_route_internal just like send_payment_internal instead of calling find_route_and_send_payment
  • send_payment_for_bolt12_invoice, send_payment_internal, and find_route_and_send_payment use a new utility to find the route to avoid repeating that code again as is already happening in the latter two functions
  • send_payment_for_bolt12_invoice calls this new route finding helper before calling pay_route_internal and uses an error enum that has two variants wrapping Bolt12PaymentError and RetryableSendFailure, respectively
  • send_payment_for_bolt12_invoice transitions the state from PendingOutboundPayment::InvoiceReceived to PendingOutboundPayment::Retryable instead of find_route_and_send_payment

It seems this will better align our BOLT11 and BOLT12 flows.

@slanesuke Feel free to take that on if you can make it a priority. We have some other work that is blocked on it. It should be mostly straightforward, though feel free to ping me on Discord if you have any questions. Otherwise, I may need to jump on it to unblock some other work.

@jkczyz
Copy link
Contributor

jkczyz commented Jul 10, 2024

  • send_payment_for_bolt12_invoice calls this new route finding helper before calling pay_route_internal and uses an error enum that has two variants wrapping Bolt12PaymentError and RetryableSendFailure, respectively

Alternatively, we could probably just add another variant to Bolt12PaymentError that wraps RetryableSendFailure.

@slanesuke
Copy link
Contributor

@jkczyz if you want, I could take this off your hands!? I can expand the Bolt12PaymentError to include a PaymentFailureReason variant and handle the places Ok is returned with more descriptive errors. Also, in pay_for_offer abort the payment if the offer amount > the available channel liquidity. If that's the approach you'd be okay with 👍

Discussing with @TheBlueMatt offline. Doesn't seem like this is the right approach. Instead, we need to refactor the code such that:

  • send_payment_for_bolt12_invoice calls pay_route_internal just like send_payment_internal instead of calling find_route_and_send_payment
  • send_payment_for_bolt12_invoice, send_payment_internal, and find_route_and_send_payment use a new utility to find the route to avoid repeating that code again as is already happening in the latter two functions
  • send_payment_for_bolt12_invoice calls this new route finding helper before calling pay_route_internal and uses an error enum that has two variants wrapping Bolt12PaymentError and RetryableSendFailure, respectively
  • send_payment_for_bolt12_invoice transitions the state from PendingOutboundPayment::InvoiceReceived to PendingOutboundPayment::Retryable instead of find_route_and_send_payment

It seems this will better align our BOLT11 and BOLT12 flows.

@slanesuke Feel free to take that on if you can make it a priority. We have some other work that is blocked on it. It should be mostly straightforward, though feel free to ping me on Discord if you have any questions. Otherwise, I may need to jump on it to unblock some other work.

@jkczyz thanks for the feedback! It sounds doable, I can take a stab at it and aim to open a PR by the end of the day tomorrow at the latest. If timing becomes/is an issue and it's more urgent, feel free to take care of it. Let me know, but either way works for me.

@jkczyz
Copy link
Contributor

jkczyz commented Jul 11, 2024

SGTM. I can work off a hacked interface change in the interim.

@tnull
Copy link
Contributor Author

tnull commented Jul 12, 2024

Now moved the second part to #3174

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Take a Friday Leave a Friday Stomp the Bugs, Without Much Commitment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants