Skip to content

Conversation

valentinewallace
Copy link
Contributor

In #4045, as part of supporting sending payments as an often-offline sender to an often-offline recipient, we began including blinded paths in the sender's LSP's RAA message for use as reply paths to the sender's held_htlc_available messages.

Because we hold the per-peer lock corresponding to the Channel while creating this RAA, we can't use our typical approach of calling ChannelManager::get_peers_for_blinded_path to create these blinded paths. The ::get_peers method takes each peer's lock in turn in order to check for usable channels/onion message feature support, and it's not permitted to hold multiple peer state locks at the same time due to the potential for deadlocks (see the debug_sync module).

To avoid taking other peer state locks while holding a particular Channel's peer state lock, here we cache the set of peers in the OffersMessageFlow, which is the struct that ultimately creates the blinded paths for the RAA.

For consistency, we also stop passing in peers to every other OffersMessageFlow method.

Based on #4045, #4046

As part of supporting sending payments as an often-offline sender, the sender
needs to be able to set a flag in their update_add_htlc message indicating that
the HTLC should be held until receipt of a release_held_htlc onion message from
the often-offline payment recipient.

We don't yet ever set this flag, but lay the groundwork by including the field
in the update_add struct.

See-also <lightning/bolts#989>
As part of supporting sending payments as an often-offline sender, the
often-offline sender's channel counterparty needs to advertise a feature bit
indicating that they support holding onto the sender's HTLC until they receive
a release_held_htlc onion message from the recipient indicating that they are
online and ready to receive the payment.

See-also <lightning/bolts#989>

We don't yet advertise support of this feature.
As part of supporting sending payments as an often-offline sender, the
often-offline sender's channel counterparty needs to advertise a feature bit
indicating that they support holding onto the sender's HTLC until they receive
a release_held_htlc onion message from the recipient indicating that they are
online and ready to receive the payment.

Here we add a config flag to turn on advertising this feature, and fail back
hold_htlcs if this config flag is not set.

See-also <lightning/bolts#989>
@ldk-reviews-bot
Copy link

👋 Hi! I see this is a draft PR.
I'll wait to assign reviewers until you mark it as ready for review.
Just convert it out of draft status when you're ready for review!

Copy link

codecov bot commented Sep 10, 2025

Codecov Report

❌ Patch coverage is 90.05947% with 117 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.30%. Comparing base (ecce859) to head (4cc7ff7).
⚠️ Report is 19 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/ln/channelmanager.rs 76.15% 58 Missing and 9 partials ⚠️
lightning/src/ln/async_payments_tests.rs 94.72% 31 Missing and 6 partials ⚠️
lightning/src/offers/flow.rs 92.85% 1 Missing and 4 partials ⚠️
lightning/src/ln/channel.rs 94.00% 2 Missing and 1 partial ⚠️
lightning/src/ln/functional_test_utils.rs 78.57% 2 Missing and 1 partial ⚠️
lightning/src/ln/outbound_payment.rs 96.29% 1 Missing ⚠️
lightning/src/util/ser_macros.rs 50.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4066      +/-   ##
==========================================
- Coverage   88.76%   88.30%   -0.47%     
==========================================
  Files         176      176              
  Lines      129518   132153    +2635     
  Branches   129518   132153    +2635     
==========================================
+ Hits       114968   116693    +1725     
- Misses      11945    12882     +937     
+ Partials     2605     2578      -27     
Flag Coverage Δ
fuzzing ?
tests 88.30% <90.05%> (-0.30%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

As part of supporting sending payments as an often-offline sender, the sender
needs to send held_htlc_available onion messages where the reply path
terminates at their always-online channel counterparty that is holding the HTLC
until the recipient comes online. That way when the recipient sends
release_held_htlc, the sender's counterparty will receive that message.

To accomplish this, the sender's always-online counterparty includes said reply
path in the revoke_and_ack message corresponding to the held HTLC. Here we add
support for this field, though we don't set it yet.

We also had to tweak the ser macros for this because impl_writeable_msg had
never had to write a Vec in a message TLV field before.
We previously had a lock order dependency where the forward_htlcs lock had to
be taken before the intercepted_htlcs lock. Here we remove this dependency,
which also prepares for a cleaner commit once we start also intercepting HTLCs
for often-offline recipients.
As part of supporting sending payments as an often-offline sender, the sender's
always-online channel counterparty needs to hold onto the sender's HTLC until
they receive a release_held_htlc onion message from the often-offline
recipient.

Here we implement storing these held HTLCs in the existing
ChannelManager::pending_intercepted_htlcs map.

We want to move in the direction of obviating the need to persistence the
ChannelManager entirely, so it doesn't really make sense to add a whole new map
for these HTLCs.
As part of supporting sending payments as an often-offline sender, the sender
needs to send held_htlc_available onion messages such that the reply path to
the message terminates at their always-online channel counterparty that is
holding the HTLC. That way when the recipient responds with release_held_htlc,
the sender's counterparty will receive that message.

Here we add a method for creating said reply path, which will be used in the
next commit.
As part of supporting sending payments as an often-offline sender, the sender
needs to send held_htlc_available onion messages such that the reply path to
the message terminates at their always-online channel counterparty that is
holding the HTLC. That way when the recipient responds with release_held_htlc,
the sender's counterparty will receive that message.

Here the counterparty starts including said reply paths in the revoke_and_ack
message destined for the sender, so the sender can use these paths in
subsequent held_htlc_available messages.

We put the paths in the RAA to ensure the sender receives the blinded paths,
because failure to deliver the paths means the HTLC will timeout/fail.
As part of supporting sending payments as an often-offline sender, the sender's
always-online channel counterparty needs to hold onto the sender's HTLC until
they receive a release_held_htlc onion message from the often-offline
recipient.

Here we implement forwarding these held HTLCs upon receipt of the release
message from the recipient.
In upcoming commits, we'll be creating blinded paths during the process of
creating a revoke_and_ack message within the Channel struct. These paths will
be included in said RAA to be used as reply paths for often-offline senders
held_htlc_available messages.

Because we hold the per-peer lock corresponding to the Channel while creating
this RAA, we can't use our typical approach of calling
ChannelManager::get_peers_for_blinded_path to create these blinded paths.
The ::get_peers method takes each peer's lock in turn in order to check for
usable channels/onion message feature support, and it's not permitted to hold
multiple peer state locks at the same time due to the potential for deadlocks
(see the debug_sync module).

To avoid taking other peer state locks while holding a particular Channel's
peer state lock, here we cache the set of peers in the OffersMessageFlow, which
is the struct that ultimately creates the blinded paths for the RAA.
Useful to filter for channel peers that support a specific feature, in this
case the hold_htlc feature, in upcoming commits.
As part of supporting sending payments as an often-offline sender, the sender
needs to be able to set a flag in their update_add_htlc message indicating that
the HTLC should be held until receipt of a release_held_htlc onion message from
the often-offline payment recipient.

We don't yet ever set this flag, but lay the groundwork by including the field
in the HTLCSource::OutboundRoute enum variant.

See-also <lightning/bolts#989>
As part of supporting sending payments as an often-offline sender, the sender
needs to be able to set a flag in their update_add_htlc message indicating that
the HTLC should be held until receipt of a release_held_htlc onion message from
the often-offline payment recipient.

We don't yet ever set this flag, but lay the groundwork by including the
parameter in the pay_route method.

See-also <lightning/bolts#989>
As part of supporting sending payments as an often-offline sender, the sender
needs to be able to set a flag in their update_add_htlc message indicating that
the HTLC should be held until receipt of a release_held_htlc onion message from
the often-offline payment recipient.

We don't yet ever set this flag, but lay the groundwork by including the field
in the outbound payment variant for static invoices.

We also add a helper method to gather channels for nodes that advertise support
for the hold_htlc feature, which will be used in the next commit.

See-also <lightning/bolts#989>
As part of supporting sending payments as an often-offline sender, the sender
needs to be able to set a flag in their update_add_htlc message indicating that
the HTLC should be held until receipt of a release_held_htlc onion message from
the often-offline payment recipient.

The prior commits laid groundwork to finally set the flag here in this commit.

See-also <lightning/bolts#989>
As part of supporting sending payments as an often-offline sender, the sender
needs to send held_htlc_available onion messages such that the reply path to
the message terminates at their always-online channel counterparty that is
holding the HTLC. That way when the recipient responds with release_held_htlc,
the sender's counterparty will receive that message.

Here we lay some groundwork for using a counterparty-created reply path when
sending held_htlc_available as an async sender in the next commit.
As part of supporting sending payments as an often-offline sender, the sender
needs to send held_htlc_available onion messages such that the reply path to
the message terminates at their always-online channel counterparty that is
holding the HTLC. That way when the recipient responds with release_held_htlc,
the sender's counterparty will receive that message.

After laying groundwork over some past commits, here we as an async sender send
held_htlc_available messages using reply paths created by our always-online
channel counterparty.
Now that we support the feature of sending payments as an often-offline sender
to an often-offline recipient, including the sender's LSP-side, we can start
conditionally advertising the feature bit to other nodes on the network.
Previously we were taking the NetworkGraph::{channels,nodes} locks before
ChannelManager::per_peer_state's peer_state locks in some tests, which violated
a lock order requirement we have in ChannelManager to take netgraph locks
*after* peer_state locks. See OffersMessageFlow::path_for_release_htlc which is
called while a peer_state lock is held and takes netgraph locks while creating
blinded paths.
Add testing for sending payments from an often-offline sender to an
often-offline recipient.
In the previous commit, we started caching the set of peers in the
OffersMessageFlow that are used when creating blinded paths. Here we start
using that cache and stop passing in the peers for every method.
@valentinewallace valentinewallace force-pushed the 2025-09-multihop-raa-paths branch from 010b2b9 to 4cc7ff7 Compare September 10, 2025 20:05
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.

2 participants