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.

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
@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
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
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.
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.
lightning/src/routing/utxo.rs Outdated Show resolved Hide resolved
lightning/src/ln/peer_handler.rs Show resolved Hide resolved
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