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

Add an async resolution option to ChainAccess::get_utxo #1980

Merged
merged 16 commits into from
Feb 11, 2023

Conversation

TheBlueMatt
Copy link
Collaborator

For those operating in an async environment, requiring
ChainAccess::get_utxo return information about the requested UTXO
synchronously is incredibly painful. Requesting information about a
random UTXO is likely to go over the network, and likely to be a
rather slow request.

Thus, here, we change the return type of get_utxo to have both a
synchronous and asynchronous form. The asynchronous form requires
the user construct a AccessFuture which they clone and pass
back to us. Internally, an AccessFuture has an Arc to the
channel_announcement message which we need to process. When the
user completes their lookup, they call resolve on their
AccessFuture which we pull the channel_announcement from and
then apply to the network graph.

Fixes #1975.

@tnull tnull self-requested a review January 23, 2023 16:09
@wpaulino wpaulino self-requested a review January 23, 2023 18:53
@TheBlueMatt TheBlueMatt force-pushed the 2023-01-async-utxo-lookups branch from 29b4b1a to 18d1a3e Compare January 23, 2023 19:03
Copy link
Contributor

@tnull tnull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Did a first pass, mostly questions and nits.

lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/ln/msgs.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/ln/peer_handler.rs Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/util/events.rs Outdated Show resolved Hide resolved
lightning/src/ln/msgs.rs Outdated Show resolved Hide resolved
@TheBlueMatt
Copy link
Collaborator Author

Addressed all the feedback and pushed one additional commit - f check_hold in the right place which ensures that we don't ever hold a channel_update/node_announcement just because we have a pending UTXO lookup for it if the relevant channel/node is already in our network graph.

lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
@TheBlueMatt TheBlueMatt force-pushed the 2023-01-async-utxo-lookups branch 2 times, most recently from 77ded8c to 52950dc Compare January 25, 2023 21:36
@TheBlueMatt
Copy link
Collaborator Author

Pushed a fix for the MSRV.

Copy link
Contributor

@wpaulino wpaulino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, mostly just minor comments

lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
fuzz/src/router.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip.rs Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
lightning/src/routing/gossip_checking.rs Outdated Show resolved Hide resolved
@TheBlueMatt TheBlueMatt force-pushed the 2023-01-async-utxo-lookups branch from 52950dc to 1f63203 Compare January 26, 2023 03:16
@codecov-commenter
Copy link

codecov-commenter commented Jan 26, 2023

Codecov Report

Base: 90.91% // Head: 90.83% // Decreases project coverage by -0.08% ⚠️

Coverage data is based on head (088be5a) compared to base (d4de913).
Patch coverage: 86.69% of modified lines in pull request are covered.

❗ Current head 088be5a differs from pull request most recent head 1806c3a. Consider uploading reports for the commit 1806c3a to get more accurate results

📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1980      +/-   ##
==========================================
- Coverage   90.91%   90.83%   -0.08%     
==========================================
  Files          99      100       +1     
  Lines       52505    53061     +556     
  Branches    52505    53061     +556     
==========================================
+ Hits        47735    48199     +464     
- Misses       4770     4862      +92     
Impacted Files Coverage Δ
lightning-background-processor/src/lib.rs 95.46% <ø> (ø)
lightning/src/chain/mod.rs 80.95% <ø> (-0.87%) ⬇️
lightning/src/ln/msgs.rs 86.22% <ø> (ø)
lightning/src/util/events.rs 30.43% <0.00%> (-0.07%) ⬇️
lightning/src/ln/peer_handler.rs 55.99% <66.19%> (+0.39%) ⬆️
lightning/src/ln/channelmanager.rs 87.23% <66.66%> (-0.05%) ⬇️
lightning/src/ln/functional_test_utils.rs 91.07% <75.00%> (-0.14%) ⬇️
lightning/src/routing/gossip.rs 91.65% <79.31%> (-0.40%) ⬇️
lightning/src/util/test_utils.rs 74.09% <83.33%> (+0.15%) ⬆️
lightning/src/routing/gossip_checking.rs 90.95% <90.95%> (ø)
... and 23 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@TheBlueMatt TheBlueMatt force-pushed the 2023-01-async-utxo-lookups branch 2 times, most recently from 61c310a to ca2f0b6 Compare January 26, 2023 18:20
@wpaulino
Copy link
Contributor

This is ready to squash. Will take another look then.

@TheBlueMatt TheBlueMatt force-pushed the 2023-01-async-utxo-lookups branch from ca2f0b6 to ebffd47 Compare January 26, 2023 19:31
@TheBlueMatt
Copy link
Collaborator Author

Squashed without further changes.

@wpaulino
Copy link
Contributor

LGTM once CI is fixed on the no-std build:

error[E0599]: no method named `to_owned` found for reference `&'static str` in the current scope
  --> lightning/src/routing/gossip_checking.rs:69:90
   |
69 |                     return Err(LightningError{err: "Channel announced without corresponding UTXO entry".to_owned(), action: ErrorActi...
   |                                                                                                         ^^^^^^^^ method not found in `&'static str`

@TheBlueMatt TheBlueMatt force-pushed the 2023-01-async-utxo-lookups branch from ebffd47 to 43f1b37 Compare January 27, 2023 05:02
@TheBlueMatt
Copy link
Collaborator Author

Fixed per-commit compile, without diff from ebffd47c9 to 43f1b37fe

wpaulino
wpaulino previously approved these changes Jan 27, 2023
tnull
tnull previously approved these changes Jan 27, 2023
Copy link
Contributor

@tnull tnull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two post-ACK questions regarding the backpressure that came to mind. Not sure if they are trivial.

lightning/src/ln/peer_handler.rs Outdated Show resolved Hide resolved
lightning/src/ln/peer_handler.rs Outdated Show resolved Hide resolved
@TheBlueMatt TheBlueMatt dismissed stale reviews from tnull and wpaulino via 9ba107e January 28, 2023 22:34
@TheBlueMatt
Copy link
Collaborator Author

Ping @wpaulino @tnull

@tnull
Copy link
Contributor

tnull commented Feb 7, 2023

Ping @wpaulino @tnull

Ah, had missed that you added the reset of received_channel_announce_since_backlogged due to the rebase. Will have another look.

@TheBlueMatt
Copy link
Collaborator Author

Had to rebase after #2016 landed. Luckily this removed a number of NodeId::from_pubkey serializes.

@TheBlueMatt TheBlueMatt force-pushed the 2023-01-async-utxo-lookups branch 2 times, most recently from dbe2f63 to 4223d2e Compare February 8, 2023 23:38
lightning/src/routing/utxo.rs Outdated Show resolved Hide resolved
The `chain::Access` trait (and the `chain::AccessError` enum) is a
bit strange - it only really makes sense if users import it via the
`chain` module, otherwise they're left with a trait just called
`Access`. Worse, for bindings users its always just called
`Access`, in part because many downstream languages don't have a
mechanism to import a module and then refer to it.

Further, its stuck dangling in the `chain` top-level mod.rs file,
sitting in a module that doesn't use it at all (it's only used in
`routing::gossip`).

Instead, we give it its full name - `UtxoLookup` (and rename the
error enum `UtxoLookupError`) and put it in the a new
`routing::utxo` module, next to `routing::gossip`.
This commit is deliberately move-only, though the code being moved
is somewhat crufty.
`check_channel_announcement` had long lines, a (very-)stale TODO
and confusing variable assignment, which is all cleaned up here.
For those operating in an async environment, requiring
`ChainAccess::get_utxo` return information about the requested UTXO
synchronously is incredibly painful. Requesting information about a
random UTXO is likely to go over the network, and likely to be a
rather slow request.

Thus, here, we change the return type of `get_utxo` to have both a
synchronous and asynchronous form. The asynchronous form requires
the user construct a `AccessFuture` which they `clone` and pass
back to us. Internally, an `AccessFuture` has an `Arc` to the
`channel_announcement` message which we need to process. When the
user completes their lookup, they call `resolve` on their
`AccessFuture` which we pull the `channel_announcement` from and
then apply to the network graph.
If we receive two `channel_announcement`s for the same channel at
the same time, we shouldn't spawn a second UTXO lookup for an
identical message. This likely isn't too rare - if we start syncing
the graph from two peers at the same time, it isn't unlikely that
we'll end up with the same messages around the same time.

In order to avoid this we keep a hash map of all the pending
`channel_announcement` messages by SCID and simply ignore duplicate
message lookups.
If we have a `channel_announcement` which is waiting on a UTXO
lookup before we can process it, and we receive a `channel_update`
or `node_announcement` for the same channel or a node which is a
part of the channel, we have to wait until the lookup completes
until we can decide if we want to accept the new message.

Here, we store the new message in the pending lookup state and
process it asynchronously like the original `channel_announcement`.
When we process gossip messages asynchronously we may find that we
want to forward a gossip message to a peer after we've returned
from the existing `handle_*` method. In order to do so, we need to
be able to send arbitrary loose gossip messages back to the
`PeerManager` via `MessageSendEvent`.

This commit modifies `MessageSendEvent` in order to support this.
@TheBlueMatt TheBlueMatt force-pushed the 2023-01-async-utxo-lookups branch from 4223d2e to 8529164 Compare February 8, 2023 23:54
Gossip messages which were verified against the chain
asynchronously should still be forwarded to peers, but must now go
out via a new `P2PGossipSync` parameter in the
`AccessResolver::resolve` method, allowing us to wire them up to
the `P2PGossipSync`'s `MessageSendEventsProvider` implementation.
Now that we allow `handle_channel_announcement` to (indirectly)
spawn async tasks which will complete later, we have to ensure it
can apply backpressure all the way up to the TCP socket to ensure
we don't end up with too many buffers allocated for UTXO
validation.

We do this by adding a new method to `RoutingMessageHandler` which
allows it to signal if there are "many" checks pending and
`channel_announcement` messages should be delayed. The actual
`PeerManager` implementation thereof is done in the next commit.
Now that the `RoutingMessageHandler` can signal that it needs to
apply message backpressure, we implement it here in the
`PeerManager`. There's not much complicated here, aside from noting
that we need to add the ability to call `send_data` with no data
to indicate that reading should resume (and track when we may need
to make such calls when updating the routing-backpressure state).
When we apply the new gossip-async-check backpressure on peer
connections, if a peer has never sent us a `channel_announcement`
at all, we really shouldn't delay reading their messages.

This does so by tracking, on a per-peer basis, whether they've sent
us a channel_announcement, and resetting that state whenever we're
not backlogged.
...and switch the same in `lightning-net-tokio`
This ensures its always written after we update the graph, no
matter how we updated the graph.
@TheBlueMatt TheBlueMatt force-pushed the 2023-01-async-utxo-lookups branch from 8529164 to 1f05575 Compare February 9, 2023 15:40
lightning/src/routing/utxo.rs Outdated Show resolved Hide resolved
lightning/src/ln/peer_handler.rs Show resolved Hide resolved
@wpaulino wpaulino merged commit be4bb58 into lightningdevkit:main Feb 11, 2023
k0k0ne pushed a commit to bitlightlabs/rust-lightning that referenced this pull request Sep 30, 2024
0.0.114 - Mar 3, 2023 - "Faster Async BOLT12 Retries"

API Updates
===========

 * `InvoicePayer` has been removed and its features moved directly into
   `ChannelManager`. As such it now requires a simplified `Router` and supports
   `send_payment_with_retry` (and friends). `ChannelManager::retry_payment` was
   removed in favor of the automated retries. Invoice payment utilities in
   `lightning-invoice` now call the new code (lightningdevkit#1812, lightningdevkit#1916, lightningdevkit#1929, lightningdevkit#2007, etc).
 * `Sign`/`BaseSign` has been renamed `ChannelSigner`, with `EcdsaChannelSigner`
   split out in anticipation of future schnorr/taproot support (lightningdevkit#1967).
 * The catch-all `KeysInterface` was split into `EntropySource`, `NodeSigner`,
   and `SignerProvider`. `KeysManager` implements all three (lightningdevkit#1910, lightningdevkit#1930).
 * `KeysInterface::get_node_secret` is now `KeysManager::get_node_secret_key`
   and is no longer required for external signers (lightningdevkit#1951, lightningdevkit#2070).
 * A `lightning-transaction-sync` crate has been added which implements keeping
   LDK in sync with the chain via an esplora server (lightningdevkit#1870). Note that it can
   only be used on nodes that *never* ran a previous version of LDK.
 * `Score` is updated in `BackgroundProcessor` instead of via `Router` (lightningdevkit#1996).
 * `ChainAccess::get_utxo` (now `UtxoAccess`) can now be resolved async (lightningdevkit#1980).
 * BOLT12 `Offer`, `InvoiceRequest`, `Invoice` and `Refund` structs as well as
   associated builders have been added. Such invoices cannot yet be paid due to
   missing support for blinded path payments (lightningdevkit#1927, lightningdevkit#1908, lightningdevkit#1926).
 * A `lightning-custom-message` crate has been added to make combining multiple
   custom messages into one enum/handler easier (lightningdevkit#1832).
 * `Event::PaymentPathFailure` is now generated for failure to send an HTLC
   over the first hop on our local channel (lightningdevkit#2014, lightningdevkit#2043).
 * `lightning-net-tokio` no longer requires an `Arc` on `PeerManager` (lightningdevkit#1968).
 * `ChannelManager::list_recent_payments` was added (lightningdevkit#1873).
 * `lightning-background-processor` `std` is now optional in async mode (lightningdevkit#1962).
 * `create_phantom_invoice` can now be used in `no-std` (lightningdevkit#1985).
 * The required final CLTV delta on inbound payments is now configurable (lightningdevkit#1878)
 * bitcoind RPC error code and message are now surfaced in `block-sync` (lightningdevkit#2057).
 * Get `historical_estimated_channel_liquidity_probabilities` was added (lightningdevkit#1961).
 * `ChannelManager::fail_htlc_backwards_with_reason` was added (lightningdevkit#1948).
 * Macros which implement serialization using TLVs or straight writing of struct
   fields are now public (lightningdevkit#1823, lightningdevkit#1976, lightningdevkit#1977).

Backwards Compatibility
=======================

 * Any inbound payments with a custom final CLTV delta will be rejected by LDK
   if you downgrade prior to receipt (lightningdevkit#1878).
 * `Event::PaymentPathFailed::network_update` will always be `None` if an
   0.0.114-generated event is read by a prior version of LDK (lightningdevkit#2043).
 * `Event::PaymentPathFailed::all_paths_removed` will always be false if an
   0.0.114-generated event is read by a prior version of LDK. Users who rely on
   it to determine payment retries should migrate to `Event::PaymentFailed`, in
   a separate release prior to upgrading to LDK 0.0.114 if downgrading is
   supported (lightningdevkit#2043).

Performance Improvements
========================

 * Channel data is now stored per-peer and channel updates across multiple
   peers can be operated on simultaneously (lightningdevkit#1507).
 * Routefinding is roughly 1.5x faster (lightningdevkit#1799).
 * Deserializing a `NetworkGraph` is roughly 6x faster (lightningdevkit#2016).
 * Memory usage for a `NetworkGraph` has been reduced substantially (lightningdevkit#2040).
 * `KeysInterface::get_secure_random_bytes` is roughly 200x faster (lightningdevkit#1974).

Bug Fixes
=========

 * Fixed a bug where a delay in processing a `PaymentSent` event longer than the
   time taken to persist a `ChannelMonitor` update, when occurring immediately
   prior to a crash, may result in the `PaymentSent` event being lost (lightningdevkit#2048).
 * Fixed spurious rejections of rapid gossip sync data when the graph has been
   updated by other means between gossip syncs (lightningdevkit#2046).
 * Fixed a panic in `KeysManager` when the high bit of `starting_time_nanos`
   is set (lightningdevkit#1935).
 * Resolved an issue where the `ChannelManager::get_persistable_update_future`
   future would fail to wake until a second notification occurs (lightningdevkit#2064).
 * Resolved a memory leak when using `ChannelManager::send_probe` (lightningdevkit#2037).
 * Fixed a deadlock on some platforms at least when using async `ChannelMonitor`
   updating (lightningdevkit#2006).
 * Removed debug-only assertions which were reachable in threaded code (lightningdevkit#1964).
 * In some cases when payment sending fails on our local channel retries no
   longer take the same path and thus never succeed (lightningdevkit#2014).
 * Retries for spontaneous payments have been fixed (lightningdevkit#2002).
 * Return an `Err` if `lightning-persister` fails to read the directory listing
   rather than panicing (lightningdevkit#1943).
 * `peer_disconnected` will now never be called without `peer_connected` (lightningdevkit#2035)

Security
========

0.0.114 fixes several denial-of-service vulnerabilities which are reachable from
untrusted input from channel counterparties or in deployments accepting inbound
connections or channels. It also fixes a denial-of-service vulnerability in rare
cases in the route finding logic.
 * The number of pending un-funded channels as well as peers without funded
   channels is now limited to avoid denial of service (lightningdevkit#1988).
 * A second `channel_ready` message received immediately after the first could
   lead to a spurious panic (lightningdevkit#2071). This issue was introduced with 0conf
   support in LDK 0.0.107.
 * A division-by-zero issue was fixed in the `ProbabilisticScorer` if the amount
   being sent (including previous-hop fees) is equal to a channel's capacity
   while walking the graph (lightningdevkit#2072). The division-by-zero was introduced with
   historical data tracking in LDK 0.0.112.

In total, this release features 130 files changed, 21457 insertions, 10113
deletions in 343 commits from 18 authors, in alphabetical order:
 * Alec Chen
 * Allan Douglas R. de Oliveira
 * Andrei
 * Arik Sosman
 * Daniel Granhão
 * Duncan Dean
 * Elias Rohrer
 * Jeffrey Czyz
 * John Cantrell
 * Kurtsley
 * Matt Corallo
 * Max Fang
 * Omer Yacine
 * Valentine Wallace
 * Viktor Tigerström
 * Wilmer Paulino
 * benthecarman
 * jurvis
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make chain::Access async-optional
4 participants