Commit graph

2950 commits

Author SHA1 Message Date
Matt Corallo
2b8c287be9 Add an integration test for InvoicePayer paying when one part fails
This tests the multi-part-single-failure-immediately fixes in the
previous commit.
2021-10-31 17:43:26 +00:00
Matt Corallo
7112661b10 Rewrite InvoicePayer retry to correctly handle MPP partial failures
This rewrites a good chunk of the retry logic in `InvoicePayer` to
address two issues:
 * it was not considering the return value of `send_payment` (and
   `retry_payment`) may indicate a failure on some paths but not
   others,
 * it was not considering that more failures may still come later
   when removing elements from the retry count map. This could
   result in us seeing an MPP-partial-failure, failing to retry,
   removing the retries count entry, and then retrying other parts,
   potentially forever.
2021-10-31 17:43:26 +00:00
Matt Corallo
e9e8a7d58d Dont unwrap RouteParameter::expiry_time as users can set it
Users can provide anything they want as `RouteParameters` so we
shouldn't assume any fields are set any particular way, including
`expiry_time` set at all.
2021-10-30 01:53:19 +00:00
Matt Corallo
51dd344f26 Expand InvoicePayer documentation somewhat to clarify edge-cases 2021-10-30 01:53:19 +00:00
Matt Corallo
d73e434280 Provide payment retry data when an MPP payment failed partially
This will allow `InvoicePayer` to properly retry payments that only
partially failed to send.
2021-10-30 01:53:19 +00:00
Matt Corallo
16f742833e Move PaymentId to a [u8; 32] in bindings as for other hash objects
This should allow us to fix
https://github.com/lightningdevkit/ldk-garbagecollected/issues/52
2021-10-30 01:53:19 +00:00
Matt Corallo
c53048a40f
Merge pull request #1144 from jkczyz/2021-10-invoice-payer-scoring
Penalize failed channels
2021-10-29 20:16:36 +00:00
Jeffrey Czyz
db05a14a0b
Test InvoicePayer in BackgroundProcessor
Proof of concept showing InvoicePayer can be used with an
Arc<ChannelManager> passed to BackgroundProcessor. Likely do not need to
merge this commit.
2021-10-29 14:26:58 -05:00
Jeffrey Czyz
c34ab42961
Penalize failed channels in Scorer
As payments fail, the channel responsible for the failure may be
penalized. Implement Scorer::payment_path_failed to penalize the failed
channel using a configured penalty. As time passes, the penalty is
reduced using exponential decay, though penalties will accumulate if the
channel continues to fail. The decay interval is also configurable.
2021-10-29 14:26:58 -05:00
Jeffrey Czyz
7a8954e1ca
Notify scorer of failing payment path and channel
Upon receiving a PaymentPathFailed event, the failing payment may be
retried on a different path. To avoid using the channel responsible for
the failure, a scorer should be notified of the failure before being
used to find a new route.

Add a payment_path_failed method to routing::Score and call it in
InvoicePayer's event handler. Introduce a LockableScore parameterization
to InvoicePayer so the scorer is locked only once before calling
find_route.
2021-10-29 14:24:53 -05:00
Matt Corallo
070e22bf09
Merge pull request #1137 from TheBlueMatt/2021-10-ping-fixes
Give peers which are sending us messages/receiving messages from us longer to respond to ping
2021-10-28 20:57:21 +00:00
Matt Corallo
0caa8bb5d5 Log peer public key more thoroughly when logging in peer_handler 2021-10-28 20:06:47 +00:00
Matt Corallo
be123f7d22 Give peers one timer tick to finish handshake before disconnecting
This ensures we don't let a hung connection stick around forever if
the peer never completes the initial handshake.

This also resolves a race where, on receiving a second connection
from a peer, we may reset their_node_id to None to prevent sending
messages even though the `channel_encryptor`
`is_ready_for_encryption()`. Sending pings only checks the
`channel_encryptor` status, not `their_node_id` resulting in an
`unwrap` on `None` in `enqueue_message`.
2021-10-28 20:06:47 +00:00
Matt Corallo
ed4a39fe1e Give peers which are sending us messages longer to respond to ping
See comment for rationale.
2021-10-28 20:06:47 +00:00
Matt Corallo
3f9a7de188 Util-ify enqueueing an encoded message in peer_handler
This marginally simplifies coming commits.
2021-10-28 20:06:47 +00:00
Matt Corallo
e496c9beb6 Constify the ratio in buf limits between forward and init sync msgs 2021-10-28 20:06:47 +00:00
Matt Corallo
6f002ea93a
Merge pull request #1142 from TheBlueMatt/2021-10-on-sent-fees
Track the amount spent on fees as payments are retried
2021-10-27 22:13:36 +00:00
Matt Corallo
04d4a8f835 Track the amount spent on fees as payments are retried
Especially once we merge the `InvoicePayer` logic soon, we'll want
to expose the total fee paid in the `PaymentSent` event.
2021-10-27 20:43:18 +00:00
Matt Corallo
af94db8111 Pass the failing/succeeding Path to PendingOutboundPayment meths
This will make the next commit much simpler
2021-10-27 20:43:18 +00:00
Matt Corallo
517a1540e0 Add a utility trait in router to get the fees along a given path 2021-10-27 20:43:18 +00:00
Matt Corallo
59659d3171
Merge pull request #1059 from jkczyz/2021-08-payment-retry
Payment Retries
2021-10-27 16:58:19 +00:00
Jeffrey Czyz
010436d07d
Implement Payer and Router for lightning crate
Implements Payer for ChannelManager and Rotuer for find_route, which can
be used to parameterize InvoicePayer when needing payment retries.
2021-10-27 10:54:53 -05:00
Jeffrey Czyz
d9b9916601
Fail payment retry if Invoice is expired
According to BOLT 11:

- after the `timestamp` plus `expiry` has passed
  - SHOULD NOT attempt a payment

Add a convenience method for checking if an Invoice has expired, and use
it to short-circuit payment retries.
2021-10-27 10:54:53 -05:00
Jeffrey Czyz
e523e58152
Support paying zero-value invoices 2021-10-27 10:54:53 -05:00
Jeffrey Czyz
ad4f16b3e6
Add InvoicePayer for retrying failed payments
When a payment fails, it's useful to retry the payment once the network
graph and channel scores are updated. InvoicePayer is a utility for
making payments which will retry any failed payment paths for a payment
up to a configured number of total attempts. It is parameterized by a
Payer and Router for ease of customization and testing.

Implement EventHandler for InvoicePayer as a decorator that intercepts
PaymentPathFailed events and retries that payment using the parameters
from the event. It delegates to the decorated EventHandler after retries
have been exhausted and for other events.
2021-10-27 10:54:39 -05:00
Jeffrey Czyz
2d102a3065
Unify route finding methods
An upcoming Router interface will be used for finding a Route both when
initially sending a payment and also when retrying failed payment paths.
Unify the three varieties of get_route so the interface can consist of a
single method implemented by the new `find_route` method. Give get_route
pub(crate) visibility so it can still be used in tests.
2021-10-26 20:15:19 -05:00
Jeffrey Czyz
5feb4dc9c4
Rewrite Invoice's interface in terms of msats
InvoiceBuilder's interface was changed recently to work in terms of
msats. Update Invoice's interface to return the amount in msats, too,
and make amount_pico_btc private.
2021-10-26 01:12:31 -05:00
Jeffrey Czyz
73f601fd3d
Add PaymentId to PaymentPathFailed event
The PaymentId is needed when retrying payments. Include it in the
PaymentPathFailed event so it can be used in that manner.
2021-10-26 01:12:30 -05:00
Jeffrey Czyz
3410f1803a
Add PaymentId to PaymentSent event
The payment_hash may not uniquely identify the payment if it has been
reused. Include the payment_id in PaymentSent events so it can
correlated with the send_payment call.
2021-10-26 01:12:30 -05:00
Jeffrey Czyz
a3a4e61427
Expose log_bytes! macro for use in other crates
Needed to log PaymentHash in the lightning-invoice crate when retrying
payments.
2021-10-26 01:12:30 -05:00
Matt Corallo
4a58e9ad83 Add PeerManager::disconnect_all_peers to avoid complexity in BP
In the coming commits simply calling `timer_tick_occurred` will no
longer disconnect all peers, so its helpful to have a utility
method.
2021-10-26 02:04:34 +00:00
Matt Corallo
10580f55aa Correct send-bounding logic in TestRoutingMessageHandler
The `cmp::min` appeared to confused `end` for a count.
2021-10-25 21:51:52 +00:00
Matt Corallo
2ed1ba653d
Merge pull request #1138 from TheBlueMatt/2021-10-payee-in-monitors
Store `Payee` info with HTLCs
2021-10-25 20:32:27 +00:00
Matt Corallo
1b99c93334 Store Payee information in HTLCSource::OutboundRoute.
This stores and tracks HTLC payee information with HTLCSource info,
allowing us to provide it back to the user if the HTLC fails and
ensuring persistence by keeping it with the HTLC itself as it
passes between Channel and ChannelMonitor.
2021-10-25 19:40:58 +00:00
Matt Corallo
fe237f9280 Copy Payee into Routes to provide them to ChannelManager 2021-10-25 17:58:18 +00:00
Matt Corallo
87da91042e Make Payee::pubkey pub.
`Payee` is expected to be used by users to get routes for payment
retries, potentially with their own router. Thus, its helpful if it
is pub, even if it is redundant with the last hop in the `path`
field in `Events::PaymentPathFailed`.
2021-10-25 17:58:18 +00:00
Matt Corallo
ca103491eb
Merge pull request #1134 from jkczyz/2021-10-payee-arg
Payee abstraction for use in get_route and PaymentPathFailed
2021-10-25 16:09:06 +00:00
Jeffrey Czyz
8e7ceabe48
Use option TLV decoding for short_channel_id
Using ignorable TLV decoding is only applicable for an Option containing
an enum, but short_channel_id is an Option<u64>. Use option TLV encoding
instead.
2021-10-25 10:18:12 -05:00
Jeffrey Czyz
46b68c517d
Include PaymentPathRetry data in PaymentPathFailed
When a payment path fails, it may be retried. Typically, this means
re-computing the route after updating the NetworkGraph and channel
scores in order to avoid the failing hop. The last hop in
PaymentPathFailed's path field contains the pubkey, amount, and CLTV
values needed to pass to get_route. However, it does not contain the
payee's features and route hints from the invoice.

Include the entire set of parameters in PaymentPathRetry and add it to
the PaymentPathFailed event. Add a get_retry_route wrapper around
get_route that takes PaymentPathRetry. This allows an EventHandler to
retry failed payment paths using the payee's route hints and features.
2021-10-25 10:18:11 -05:00
Jeffrey Czyz
8b9cf93b11
Remove outdated line from get_route docs 2021-10-25 10:18:11 -05:00
Jeffrey Czyz
b5be4c210c
Define Payee abstraction for use in get_route
A payee can be identified by a pubkey and optionally have an associated
set of invoice features and route hints. Use this in get_route instead
of three separate parameters. This may be included in PaymentPathFailed
later to use when finding a new route.
2021-10-25 10:18:11 -05:00
Matt Corallo
0a31c12f85
Merge pull request #1104 from TheBlueMatt/2021-10-payment-id-in-monitors
Reload pending outbound payments from ChannelMonitors on startup
2021-10-22 19:33:33 +00:00
Matt Corallo
7af5d127ac Add a test of an HTLC being fulfilled and then later failed
Peers probably shouldn't do this, but if they want to give us free
money, we should take it and not generate any spurious events.
2021-10-22 18:41:42 +00:00
Matt Corallo
251eb3bda8 Move test_dup_htlc_onchain_fails_on_reload to payment_tests
test_dup_htlc_onchain_fails_on_reload is now more of a
payment_test than a functional_test, testing for handling of
pending payments.
2021-10-22 18:41:42 +00:00
Matt Corallo
5296a4a04d Add some basic test coverage of monitor payment data reloading 2021-10-22 18:41:42 +00:00
Matt Corallo
fe660c5786 Reload pending payments from ChannelMonitor HTLC data on reload
If we go to send a payment, add the HTLC(s) to the channel(s),
commit the ChannelMonitor updates to disk, and then crash, we'll
come back up with no pending payments but HTLC(s) ready to be
claim/failed.

This makes it rather impractical to write a payment sender/retryer,
as you cannot guarantee atomicity - you cannot guarantee you'll
have retry data persisted even if the HTLC(s) are actually pending.

Because ChannelMonitors are *the* atomically-persisted data in LDK,
we lean on their current HTLC data to figure out what HTLC(s) are a
part of an outbound payment, rebuilding the pending payments list
on reload.
2021-10-22 18:41:42 +00:00
Matt Corallo
0d5050833d Add PaymentSecrets to HTLCSource::OutboundRoute objects 2021-10-22 18:41:42 +00:00
Matt Corallo
2727c52d3c Rename payment object vars to refer to payments and not session IDs 2021-10-22 18:41:42 +00:00
Matt Corallo
5fedae85d1 Track payments after they resolve until all HTLCs are finalized
In the next commit, we will reload lost pending payments from
ChannelMonitors during restart. However, in order to avoid
re-adding pending payments which have already been fulfilled, we
must ensure that we do not fully remove pending payments until all
HTLCs for the payment have been fully removed from their
ChannelMonitors.

We do so here, introducing a new PendingOutboundPayment variant
called `Completed` which only tracks the set of pending HTLCs.
2021-10-22 18:41:42 +00:00
Matt Corallo
f624cc9ac2 Inform ChannelManager when fulfilled HTLCs are finalized
When an HTLC has been failed, we track it up until the point there
exists no broadcastable commitment transaction which has the HTLC
present, at which point Channel returns the HTLCSource back to the
ChannelManager, which fails the HTLC backwards appropriately.

When an HTLC is fulfilled, however, we fulfill on the backwards path
immediately. This is great for claiming upstream HTLCs, but when we
want to track pending payments, we need to ensure we can check with
ChannelMonitor data to rebuild pending payments. In order to do so,
we need an event similar to the HTLC failure event, but for
fulfills instead.

Specifically, if we force-close a channel, we remove its off-chain
`Channel` object entirely, at which point, on reload, we may notice
HTLC(s) which are not present in our pending payments map (as they
may have received a payment preimage, but not fully committed to
it). Thus, we'd conclude we still have a retryable payment, which
is untrue.

This commit does so, informing the ChannelManager via a new return
element where appropriate of the HTLCSource corresponding to the
failed HTLC.
2021-10-22 18:41:42 +00:00